870 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			870 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System;
 | 
						||
using System.Collections.Generic;
 | 
						||
using System.ComponentModel;
 | 
						||
using System.Diagnostics.CodeAnalysis;
 | 
						||
using System.Linq;
 | 
						||
using System.Reflection;
 | 
						||
using System.Runtime.CompilerServices;
 | 
						||
using System.Text;
 | 
						||
using System.Threading.Tasks;
 | 
						||
using System.Windows;
 | 
						||
using System.Windows.Controls;
 | 
						||
using System.Windows.Controls.Primitives;
 | 
						||
using System.Windows.Data;
 | 
						||
using System.Windows.Documents;
 | 
						||
using System.Windows.Input;
 | 
						||
using System.Windows.Media;
 | 
						||
using System.Windows.Media.Imaging;
 | 
						||
using System.Windows.Navigation;
 | 
						||
using System.Windows.Shapes;
 | 
						||
 | 
						||
namespace Deedy.Activity
 | 
						||
{
 | 
						||
    /// <summary>
 | 
						||
    /// 用于为Action提供显示视图
 | 
						||
    /// </summary>
 | 
						||
    [IconKey(ThemeKeys.KEY_Activity_DefaultIcon)]
 | 
						||
    [TemplatePart(Name = PART_ItemsContainer, Type = typeof(ItemsControl))]
 | 
						||
    [TemplatePart(Name = PART_TitleContainer, Type = typeof(FrameworkElement))]
 | 
						||
    [TemplatePart(Name = PART_StateDecorator, Type = typeof(ViewerStateDecorator))]
 | 
						||
    public class ActionViewer : Control, IActionViewer
 | 
						||
    {
 | 
						||
        public const string PART_ItemsContainer = "PART_ItemsContainer";
 | 
						||
        public const string PART_TitleContainer = "PART_TitleContainer";
 | 
						||
        public const string PART_StateDecorator = "PART_StateDecorator";
 | 
						||
        [AllowNull]
 | 
						||
        protected internal ItemsControl ItemsContainer;
 | 
						||
        [AllowNull]
 | 
						||
        protected internal FrameworkElement TitleContainer;
 | 
						||
        [AllowNull]
 | 
						||
        protected internal ViewerStateDecorator StateDecorator;
 | 
						||
        static ActionViewer()
 | 
						||
        {
 | 
						||
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ActionViewer), new FrameworkPropertyMetadata(typeof(ActionViewer)));
 | 
						||
        }
 | 
						||
        public ActionViewer()
 | 
						||
        {
 | 
						||
            ToolTipService.SetInitialShowDelay(this, 0);
 | 
						||
            ToolTipService.SetBetweenShowDelay(this, 0);
 | 
						||
            this.LogInfos = new();
 | 
						||
        }
 | 
						||
        public override void OnApplyTemplate()
 | 
						||
        {
 | 
						||
            base.OnApplyTemplate();
 | 
						||
            this.ItemsContainer = this.GetTemplateChild(PART_ItemsContainer) as ItemsControl;
 | 
						||
            this.TitleContainer = this.GetTemplateChild(PART_TitleContainer) as FrameworkElement;
 | 
						||
            this.StateDecorator = this.GetTemplateChild(PART_StateDecorator) as ViewerStateDecorator;
 | 
						||
            this.RefreshViewerState();
 | 
						||
        }
 | 
						||
        public event PropertyChangedEventHandler? PropertyChanged;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 发送属性变更通知
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="propertyName">发生变更的属性</param>
 | 
						||
        protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
 | 
						||
        /// <summary>
 | 
						||
        /// 读取一个字段的值
 | 
						||
        /// </summary>
 | 
						||
        /// <typeparam name="T">值的类型,可以通过参数进行自动判定</typeparam>
 | 
						||
        /// <param name="field">字段的引用【注意:此参数通过引用传递】</param>
 | 
						||
        /// <param name="propertyName">属性名称;如果在属性的读取访问器中调用可以自动注入</param>
 | 
						||
        /// <returns>字段中的值</returns>
 | 
						||
        protected virtual T GetField<T>(ref T field, [CallerMemberName] string? propertyName = null)
 | 
						||
        {
 | 
						||
            //TODO:这里处理内部属性获取逻辑(包括运行时参数映射逻辑)
 | 
						||
            return field;
 | 
						||
        }
 | 
						||
        /// <summary>
 | 
						||
        /// 检查新值是否与原值相等,如果不相等便赋值并发出通知
 | 
						||
        /// </summary>
 | 
						||
        /// <typeparam name="T">值的类型,可以通过参数进行自动判定</typeparam>
 | 
						||
        /// <param name="field">字段的引用【注意:此参数通过引用传递】</param>
 | 
						||
        /// <param name="value">字段的新值</param>
 | 
						||
        /// <param name="propertyName">要进行变更通知的属性名称;如果在属性的设置访问器中调用可以自动注入</param>
 | 
						||
        /// <returns>值是否有变更</returns>
 | 
						||
        protected virtual bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
 | 
						||
        {
 | 
						||
            if (EqualityComparer<T>.Default.Equals(field, value)) return false;
 | 
						||
            //TODO:这里处理内部属性变更逻辑(包括运行时参数映射逻辑)
 | 
						||
            field = value;
 | 
						||
            OnPropertyChanged(propertyName);
 | 
						||
            return true;
 | 
						||
        }
 | 
						||
        [AllowNull]
 | 
						||
        public Runtime Runtime { get; protected internal set; }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 是否显示Break控制手柄
 | 
						||
        /// </summary>
 | 
						||
        public Visibility ShowBreakHandle
 | 
						||
        {
 | 
						||
            get { return (Visibility)GetValue(ShowBreakHandleProperty); }
 | 
						||
            protected internal set { SetValue(ShowBreakHandlePropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey ShowBreakHandlePropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("ShowBreakHandle", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Collapsed));
 | 
						||
        public static readonly DependencyProperty ShowBreakHandleProperty = ShowBreakHandlePropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 是否显示重手柄
 | 
						||
        /// </summary>
 | 
						||
        public Visibility ShowContinueHandle
 | 
						||
        {
 | 
						||
            get { return (Visibility)GetValue(ShowContinueHandleProperty); }
 | 
						||
            protected internal set { SetValue(ShowContinueHandlePropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey ShowContinueHandlePropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("ShowContinueHandle", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Collapsed));
 | 
						||
        public static readonly DependencyProperty ShowContinueHandleProperty = ShowContinueHandlePropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 是否显示退出手柄
 | 
						||
        /// </summary>
 | 
						||
        public Visibility ShowExitHandle
 | 
						||
        {
 | 
						||
            get { return (Visibility)GetValue(ShowExitHandleProperty); }
 | 
						||
            protected internal set { SetValue(ShowExitHandlePropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey ShowExitHandlePropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("ShowExitHandle", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Collapsed));
 | 
						||
        public static readonly DependencyProperty ShowExitHandleProperty = ShowExitHandlePropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 是否显示返回手柄
 | 
						||
        /// </summary>
 | 
						||
        public Visibility ShowReturnHandle
 | 
						||
        {
 | 
						||
            get { return (Visibility)GetValue(ShowReturnHandleProperty); }
 | 
						||
            protected internal set { SetValue(ShowReturnHandlePropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey ShowReturnHandlePropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("ShowReturnHandle", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Collapsed));
 | 
						||
        public static readonly DependencyProperty ShowReturnHandleProperty = ShowReturnHandlePropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 是否显示自定义手柄
 | 
						||
        /// </summary>
 | 
						||
        public Visibility ShowCustomizeHandle
 | 
						||
        {
 | 
						||
            get { return (Visibility)GetValue(ShowCustomizeHandleProperty); }
 | 
						||
            protected internal set { SetValue(ShowCustomizeHandlePropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey ShowCustomizeHandlePropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("ShowCustomizeHandle", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Collapsed));
 | 
						||
        public static readonly DependencyProperty ShowCustomizeHandleProperty = ShowCustomizeHandlePropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 是否显示进入区
 | 
						||
        /// </summary>
 | 
						||
        public Visibility ShowEntryZone
 | 
						||
        {
 | 
						||
            get { return (Visibility)GetValue(ShowEntryZoneProperty); }
 | 
						||
            protected internal set { SetValue(ShowEntryZonePropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey ShowEntryZonePropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("ShowEntryZone", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Visible));
 | 
						||
        public static readonly DependencyProperty ShowEntryZoneProperty = ShowEntryZonePropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 是否显示退出区
 | 
						||
        /// </summary>
 | 
						||
        public Visibility ShowLeaveZone
 | 
						||
        {
 | 
						||
            get { return (Visibility)GetValue(ShowLeaveZoneProperty); }
 | 
						||
            protected internal set { SetValue(ShowLeaveZonePropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey ShowLeaveZonePropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("ShowLeaveZone", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Visible));
 | 
						||
        public static readonly DependencyProperty ShowLeaveZoneProperty = ShowLeaveZonePropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 是否显示消息回显
 | 
						||
        /// </summary>
 | 
						||
        public Visibility ShowInfoHandle
 | 
						||
        {
 | 
						||
            get { return (Visibility)GetValue(ShowInfoHandleProperty); }
 | 
						||
            protected internal set { SetValue(ShowInfoHandlePropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey ShowInfoHandlePropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("ShowInfoHandle", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Collapsed));
 | 
						||
        public static readonly DependencyProperty ShowInfoHandleProperty = ShowInfoHandlePropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 是否显示删除图标
 | 
						||
        /// </summary>
 | 
						||
        public Visibility ShowDeleteHandle
 | 
						||
        {
 | 
						||
            get { return (Visibility)GetValue(ShowDeleteHandleProperty); }
 | 
						||
            protected internal set { SetValue(ShowDeleteHandlePropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey ShowDeleteHandlePropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("ShowDeleteHandle", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Collapsed));
 | 
						||
        public static readonly DependencyProperty ShowDeleteHandleProperty = ShowDeleteHandlePropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 显示左侧退出线
 | 
						||
        /// </summary>
 | 
						||
        public Visibility ShowLeftExitline
 | 
						||
        {
 | 
						||
            get { return (Visibility)GetValue(ShowLeftExitlineProperty); }
 | 
						||
            protected internal set { SetValue(ShowLeftExitlinePropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey ShowLeftExitlinePropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("ShowLeftExitline", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Collapsed));
 | 
						||
        public static readonly DependencyProperty ShowLeftExitlineProperty = ShowLeftExitlinePropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 显示右侧退出线
 | 
						||
        /// </summary>
 | 
						||
        public Visibility ShowRightExitline
 | 
						||
        {
 | 
						||
            get { return (Visibility)GetValue(ShowRightExitlineProperty); }
 | 
						||
            protected internal set { SetValue(ShowRightExitlinePropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey ShowRightExitlinePropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("ShowRightExitline", typeof(Visibility), typeof(ActionViewer), new PropertyMetadata(Visibility.Collapsed));
 | 
						||
        public static readonly DependencyProperty ShowRightExitlineProperty = ShowRightExitlinePropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 即时消息
 | 
						||
        /// </summary>
 | 
						||
        public LogInfo InstantInfo
 | 
						||
        {
 | 
						||
            get { return (LogInfo)GetValue(InstantInfoProperty); }
 | 
						||
            protected internal set { SetValue(InstantInfoPropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey InstantInfoPropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("InstantInfo", typeof(LogInfo), typeof(ActionViewer), new PropertyMetadata(LogInfo.Empty,
 | 
						||
                (d, e) => (d as ActionViewer)?.InstantInfo_PropertyChangedCallback(e)));
 | 
						||
        public static readonly DependencyProperty InstantInfoProperty = InstantInfoPropertyKey.DependencyProperty;
 | 
						||
        /// <summary>
 | 
						||
        /// 处理「ActionViewer.InstantInfo」属性变更
 | 
						||
        /// </summary>
 | 
						||
        protected virtual void InstantInfo_PropertyChangedCallback(DependencyPropertyChangedEventArgs e)
 | 
						||
        {
 | 
						||
            if (e.NewValue is LogInfo logInfo)
 | 
						||
            {
 | 
						||
                this.ToolTip = logInfo.ToString();
 | 
						||
                //TODO:更新消息显示图标
 | 
						||
                this.LogInfos.Add(logInfo);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 信息列表
 | 
						||
        /// </summary>
 | 
						||
        public LogInfoCollection LogInfos
 | 
						||
        {
 | 
						||
            get { return (LogInfoCollection)GetValue(LogInfosProperty); }
 | 
						||
            protected internal set { SetValue(LogInfosPropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey LogInfosPropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("LogInfos", typeof(LogInfoCollection), typeof(ActionViewer), new PropertyMetadata(null));
 | 
						||
        public static readonly DependencyProperty LogInfosProperty = LogInfosPropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 子元素数量
 | 
						||
        /// </summary>
 | 
						||
        public int ElementCount
 | 
						||
        {
 | 
						||
            get { return (int)GetValue(ElementCountProperty); }
 | 
						||
            protected internal set { SetValue(ElementCountPropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey ElementCountPropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("ElementCount", typeof(int), typeof(ActionViewer), new PropertyMetadata(0));
 | 
						||
        public static readonly DependencyProperty ElementCountProperty = ElementCountPropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 是否可被选中
 | 
						||
        /// </summary>
 | 
						||
        public bool IsSelectable
 | 
						||
        {
 | 
						||
            get { return (bool)GetValue(IsSelectableProperty); }
 | 
						||
            protected internal set { SetValue(IsSelectablePropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey IsSelectablePropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("IsSelectable", typeof(bool), typeof(ActionViewer), new PropertyMetadata(true));
 | 
						||
        public static readonly DependencyProperty IsSelectableProperty = IsSelectablePropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 是否选中
 | 
						||
        /// </summary>
 | 
						||
        public bool IsSelected
 | 
						||
        {
 | 
						||
            get { return (bool)GetValue(IsSelectedProperty); }
 | 
						||
            protected internal set { SetValue(IsSelectedPropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey IsSelectedPropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("IsSelected", typeof(bool), typeof(ActionViewer), new PropertyMetadata(false,
 | 
						||
                (d, e) => (d as ActionViewer)?.IsSelected_PropertyChangedCallback(e)));
 | 
						||
        public static readonly DependencyProperty IsSelectedProperty = IsSelectedPropertyKey.DependencyProperty;
 | 
						||
        /// <summary>
 | 
						||
        /// 处理「ActionViewer.IsSelected」属性变更
 | 
						||
        /// </summary>
 | 
						||
        protected virtual void IsSelected_PropertyChangedCallback(DependencyPropertyChangedEventArgs e)
 | 
						||
        {
 | 
						||
            if ((bool)e.NewValue)
 | 
						||
            {
 | 
						||
                //TODO:发送节点选中事件
 | 
						||
                if (this.ActionElement is IContainerForFunction container)
 | 
						||
                {
 | 
						||
                    if (container.IsEmbedded) this.IsExpanded = true;
 | 
						||
                    else
 | 
						||
                    {
 | 
						||
                        //TODO:发送打开辅助编辑器事件
 | 
						||
                    }
 | 
						||
                }
 | 
						||
            }
 | 
						||
            this.RefreshViewerState();
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 是否可被展开
 | 
						||
        /// </summary>
 | 
						||
        public bool IsExpandable
 | 
						||
        {
 | 
						||
            get { return (bool)GetValue(IsExpandableProperty); }
 | 
						||
            protected internal set { SetValue(IsExpandablePropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey IsExpandablePropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("IsExpandable", typeof(bool), typeof(ActionViewer), new PropertyMetadata(true));
 | 
						||
        public static readonly DependencyProperty IsExpandableProperty = IsExpandablePropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 是否展开
 | 
						||
        /// </summary>
 | 
						||
        public bool IsExpanded
 | 
						||
        {
 | 
						||
            get { return (bool)GetValue(IsExpandedProperty); }
 | 
						||
            protected internal set { SetValue(IsExpandedPropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey IsExpandedPropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("IsExpanded", typeof(bool), typeof(ActionViewer), new PropertyMetadata(true));
 | 
						||
        public static readonly DependencyProperty IsExpandedProperty = IsExpandedPropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 是否可被拖动
 | 
						||
        /// </summary>
 | 
						||
        public bool IsDraggable
 | 
						||
        {
 | 
						||
            get { return (bool)GetValue(IsDraggableProperty); }
 | 
						||
            protected internal set { SetValue(IsDraggablePropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey IsDraggablePropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("IsDraggable", typeof(bool), typeof(ActionViewer), new PropertyMetadata(true));
 | 
						||
        public static readonly DependencyProperty IsDraggableProperty = IsDraggablePropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 是否正在拖动
 | 
						||
        /// </summary>
 | 
						||
        public bool IsDragging
 | 
						||
        {
 | 
						||
            get { return (bool)GetValue(IsDraggingProperty); }
 | 
						||
            protected internal set { SetValue(IsDraggingPropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey IsDraggingPropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("IsDragging", typeof(bool), typeof(ActionViewer), new PropertyMetadata(false));
 | 
						||
        public static readonly DependencyProperty IsDraggingProperty = IsDraggingPropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 视图状态
 | 
						||
        /// </summary>
 | 
						||
        public ViewerState ViewerState
 | 
						||
        {
 | 
						||
            get { return (ViewerState)GetValue(ViewerStateProperty); }
 | 
						||
            protected internal set { SetValue(ViewerStatePropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey ViewerStatePropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("ViewerState", typeof(ViewerState), typeof(ActionViewer), new PropertyMetadata(ViewerState.Normal,
 | 
						||
                (d, e) => (d as ActionViewer)?.ViewerState_PropertyChangedCallback(e)));
 | 
						||
        public static readonly DependencyProperty ViewerStateProperty = ViewerStatePropertyKey.DependencyProperty;
 | 
						||
        /// <summary>
 | 
						||
        /// 处理「ActionViewer.ViewerState」属性变更
 | 
						||
        /// </summary>
 | 
						||
        protected virtual void ViewerState_PropertyChangedCallback(DependencyPropertyChangedEventArgs e)
 | 
						||
        {
 | 
						||
            this.StyleSelector?.SelectStyle(this.ActionElement, this);
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 工作模式:非设计模式下不允许拖放操作;编辑、运行、回显三种模式不可相互切换,但可以与等待和预览状态切换。
 | 
						||
        /// </summary>
 | 
						||
        public WorkMode WorkMode
 | 
						||
        {
 | 
						||
            get { return (WorkMode)GetValue(WorkModeProperty); }
 | 
						||
            protected internal set { SetValue(WorkModePropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey WorkModePropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("WorkMode", typeof(WorkMode), typeof(ActionViewer), new PropertyMetadata(WorkMode.Waiting));
 | 
						||
        public static readonly DependencyProperty WorkModeProperty = WorkModePropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 填充画刷
 | 
						||
        /// </summary>
 | 
						||
        public Brush FillBrush
 | 
						||
        {
 | 
						||
            get { return (Brush)GetValue(FillBrushProperty); }
 | 
						||
            set { SetValue(FillBrushProperty, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyProperty FillBrushProperty =
 | 
						||
            DependencyProperty.Register("FillBrush", typeof(Brush), typeof(ActionViewer), new PropertyMetadata(Brushes.Gray));
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 画线画刷
 | 
						||
        /// </summary>
 | 
						||
        public Brush StrokeBrush
 | 
						||
        {
 | 
						||
            get { return (Brush)GetValue(StrokeBrushProperty); }
 | 
						||
            set { SetValue(StrokeBrushProperty, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyProperty StrokeBrushProperty =
 | 
						||
            DependencyProperty.Register("StrokeBrush", typeof(Brush), typeof(ActionViewer), new PropertyMetadata(Brushes.Orange));
 | 
						||
        /// <summary>
 | 
						||
        /// 画线宽度
 | 
						||
        /// </summary>
 | 
						||
        public double StrokeThickness
 | 
						||
        {
 | 
						||
            get { return (double)GetValue(StrokeThicknessProperty); }
 | 
						||
            set { SetValue(StrokeThicknessProperty, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyProperty StrokeThicknessProperty =
 | 
						||
            DependencyProperty.Register("StrokeThickness", typeof(double), typeof(ActionViewer), new PropertyMetadata(2.0,
 | 
						||
                (d, e) => (d as ActionViewer)?.StrokeThickness_PropertyChangedCallback(e)));
 | 
						||
        /// <summary>
 | 
						||
        /// 处理「ActionViewer.StrokeThickness」属性变更
 | 
						||
        /// </summary>
 | 
						||
        protected virtual void StrokeThickness_PropertyChangedCallback(DependencyPropertyChangedEventArgs e)
 | 
						||
        {
 | 
						||
            if (e.NewValue is double value)
 | 
						||
            {
 | 
						||
                if (value < 2)
 | 
						||
                {
 | 
						||
                    this.StrokeThickness = 2;
 | 
						||
                    return;
 | 
						||
                }
 | 
						||
                double halfValue = value / 2;
 | 
						||
                this.MarginCorrection_Top = new Thickness(0, halfValue, 0, 0);
 | 
						||
                this.MarginCorrection_Bottom = new Thickness(0, 0, 0, halfValue);
 | 
						||
                this.MarginCorrection_TopBottom = new Thickness(0, halfValue, 0, halfValue);
 | 
						||
            }
 | 
						||
            else this.StrokeThickness = 2;
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 被托管动作元素的图标
 | 
						||
        /// </summary>
 | 
						||
        public ImageSource ElementIcon
 | 
						||
        {
 | 
						||
            get { return (ImageSource)GetValue(ElementIconProperty); }
 | 
						||
            protected internal set { SetValue(ElementIconPropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey ElementIconPropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("ElementIcon", typeof(ImageSource), typeof(ActionViewer), new PropertyMetadata(null));
 | 
						||
        public static readonly DependencyProperty ElementIconProperty = ElementIconPropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 视图样式选择器
 | 
						||
        /// </summary>
 | 
						||
        [AllowNull]
 | 
						||
        public StyleSelector StyleSelector
 | 
						||
        {
 | 
						||
            get { return (StyleSelector)GetValue(StyleSelectorProperty); }
 | 
						||
            set { SetValue(StyleSelectorProperty, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyProperty StyleSelectorProperty =
 | 
						||
            DependencyProperty.Register("StyleSelector", typeof(StyleSelector), typeof(ActionViewer), new PropertyMetadata(null));
 | 
						||
        /// <summary>
 | 
						||
        /// 上边距修正
 | 
						||
        /// </summary>
 | 
						||
        public Thickness MarginCorrection_Top
 | 
						||
        {
 | 
						||
            get { return (Thickness)GetValue(MarginCorrection_TopProperty); }
 | 
						||
            protected internal set { SetValue(MarginCorrection_TopPropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey MarginCorrection_TopPropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("MarginCorrection_Top", typeof(Thickness), typeof(ActionViewer), new PropertyMetadata(new Thickness()));
 | 
						||
        public static readonly DependencyProperty MarginCorrection_TopProperty = MarginCorrection_TopPropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 下边距修正
 | 
						||
        /// </summary>
 | 
						||
        public Thickness MarginCorrection_Bottom
 | 
						||
        {
 | 
						||
            get { return (Thickness)GetValue(MarginCorrection_BottomProperty); }
 | 
						||
            protected internal set { SetValue(MarginCorrection_BottomPropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey MarginCorrection_BottomPropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("MarginCorrection_Bottom", typeof(Thickness), typeof(ActionViewer), new PropertyMetadata(new Thickness()));
 | 
						||
        public static readonly DependencyProperty MarginCorrection_BottomProperty = MarginCorrection_BottomPropertyKey.DependencyProperty;
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 上下边距修正
 | 
						||
        /// </summary>
 | 
						||
        public Thickness MarginCorrection_TopBottom
 | 
						||
        {
 | 
						||
            get { return (Thickness)GetValue(MarginCorrection_TopBottomProperty); }
 | 
						||
            protected internal set { SetValue(MarginCorrection_TopBottomPropertyKey, value); }
 | 
						||
        }
 | 
						||
        public static readonly DependencyPropertyKey MarginCorrection_TopBottomPropertyKey =
 | 
						||
            DependencyProperty.RegisterReadOnly("MarginCorrection_TopBottom", typeof(Thickness), typeof(ActionViewer), new PropertyMetadata(new Thickness()));
 | 
						||
        public static readonly DependencyProperty MarginCorrection_TopBottomProperty = MarginCorrection_TopBottomPropertyKey.DependencyProperty;
 | 
						||
        /// <summary>
 | 
						||
        /// 动作节点
 | 
						||
        /// </summary>
 | 
						||
        [AllowNull, DefaultValue(null)]
 | 
						||
        public IActionElement ActionElement
 | 
						||
        {
 | 
						||
            get { return (IActionElement)GetValue(ActionElementProperty); }
 | 
						||
            set { SetValue(ActionElementProperty, value); }
 | 
						||
        }
 | 
						||
 | 
						||
        public static readonly DependencyProperty ActionElementProperty =
 | 
						||
            DependencyProperty.Register("ActionElement", typeof(IActionElement), typeof(ActionViewer), new PropertyMetadata(null,
 | 
						||
                (d, e) => (d as ActionViewer)?.ActionElement_PropertyChangedCallback(e)));
 | 
						||
        /// <summary>
 | 
						||
        /// 处理「ActionElementViewer.ActionElement」属性变更
 | 
						||
        /// </summary>
 | 
						||
        protected virtual void ActionElement_PropertyChangedCallback(DependencyPropertyChangedEventArgs e)
 | 
						||
        {
 | 
						||
            if (e.OldValue is IActionElement oldValue)
 | 
						||
            {
 | 
						||
                oldValue.PropertyChanged -= ActionElement_PropertyChanged;
 | 
						||
                if (oldValue is ICombinedElement combinedElement)
 | 
						||
                {
 | 
						||
                    this.ElementCount = 0;
 | 
						||
                    combinedElement.Elements.CollectionChanged -= Elements_CollectionChanged;
 | 
						||
                }
 | 
						||
                this.ShowEntryZone = Visibility.Visible;
 | 
						||
                this.ShowLeaveZone = Visibility.Visible;
 | 
						||
                this.ShowLeftExitline = Visibility.Collapsed;
 | 
						||
                this.ShowRightExitline = Visibility.Collapsed;
 | 
						||
                this.ShowBreakHandle = Visibility.Collapsed;
 | 
						||
                this.ShowContinueHandle = Visibility.Collapsed;
 | 
						||
                this.ShowCustomizeHandle = Visibility.Collapsed;
 | 
						||
                this.ShowExitHandle = Visibility.Collapsed;
 | 
						||
                this.ShowReturnHandle = Visibility.Collapsed;
 | 
						||
            }
 | 
						||
            if (e.NewValue is IActionElement newValue)
 | 
						||
            {
 | 
						||
                newValue.PropertyChanged += ActionElement_PropertyChanged;
 | 
						||
 | 
						||
                Type elementType = newValue.GetType();
 | 
						||
                IconKeyAttribute? iconKey = elementType.GetCustomAttribute<IconKeyAttribute>();
 | 
						||
                if (iconKey != null)
 | 
						||
                {
 | 
						||
                    ImageSource? icon = iconKey.TryFindResource(this) as ImageSource;
 | 
						||
                    if (icon != null) this.ElementIcon = icon;
 | 
						||
                    else
 | 
						||
                    {
 | 
						||
                        iconKey = this.GetType().GetCustomAttribute<IconKeyAttribute>();
 | 
						||
                        if (iconKey != null) icon = iconKey.TryFindResource(this) as ImageSource;
 | 
						||
 | 
						||
                        if (icon != null) this.ElementIcon = icon;
 | 
						||
                        else this.ClearValue(ElementIconPropertyKey);
 | 
						||
                    }
 | 
						||
                }
 | 
						||
 | 
						||
                if (newValue.IsLockedElement)
 | 
						||
                {
 | 
						||
                    this.IsDraggable = false;
 | 
						||
                    this.IsSelectable = newValue is IContainerForFunction;
 | 
						||
                }
 | 
						||
                else
 | 
						||
                {
 | 
						||
                    this.IsDraggable = true;
 | 
						||
                    this.IsSelectable = true;
 | 
						||
                }
 | 
						||
 | 
						||
                if (newValue is ICombinedElement newCombined)
 | 
						||
                {
 | 
						||
                    this.IsExpandable = true;
 | 
						||
                    this.ElementCount = newCombined.Elements.Count;
 | 
						||
                    newCombined.Elements.CollectionChanged += Elements_CollectionChanged;
 | 
						||
                }
 | 
						||
                else this.IsExpandable = false;
 | 
						||
 | 
						||
                if (newValue is ICriticalZoneManageable criticalZone)
 | 
						||
                {
 | 
						||
                    if (criticalZone.IsLeaveZoneHidden) this.ShowLeaveZone = Visibility.Collapsed;
 | 
						||
                    if (criticalZone.IsEntryZoneHidden) this.ShowEntryZone = Visibility.Collapsed;
 | 
						||
                }
 | 
						||
 | 
						||
                if (newValue is IContainerWithExitline withExitline)
 | 
						||
                {
 | 
						||
                    if (withExitline.ExitlinePosition.HasFlag(ExitlinePosition.LeftLower))
 | 
						||
                        this.ShowLeftExitline = Visibility.Visible;
 | 
						||
                    if (withExitline.ExitlinePosition.HasFlag(ExitlinePosition.Rightlower))
 | 
						||
                        this.ShowRightExitline = Visibility.Visible;
 | 
						||
                    // 新元素被托管渲染后调整子元素退出线位置
 | 
						||
                    withExitline.AdjustExitlinePosition();
 | 
						||
                }
 | 
						||
 | 
						||
                if (newValue is ILogicController logicController)
 | 
						||
                {
 | 
						||
                    switch (logicController.LogicalBehavior)
 | 
						||
                    {
 | 
						||
                        case LogicalBehavior.Exit: this.ShowExitHandle = Visibility.Visible; break;
 | 
						||
                        case LogicalBehavior.Return: this.ShowReturnHandle = Visibility.Visible; break;
 | 
						||
                        case LogicalBehavior.Break: this.ShowBreakHandle = Visibility.Visible; break;
 | 
						||
                        case LogicalBehavior.Continue: this.ShowContinueHandle = Visibility.Visible; break;
 | 
						||
                        case LogicalBehavior.Customize: this.ShowCustomizeHandle = Visibility.Visible; break;
 | 
						||
                        default: break;
 | 
						||
                    }
 | 
						||
                }
 | 
						||
                //TODO:根据节点的特征与当前工作状态来判定如何处理当前视图的属性
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        protected virtual void Elements_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
 | 
						||
        {
 | 
						||
            if (this.ActionElement is ICombinedElement combined)
 | 
						||
            {
 | 
						||
                if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
 | 
						||
                    this.IsExpanded = true;
 | 
						||
                this.ElementCount = combined.Elements.Count;
 | 
						||
            }
 | 
						||
            // 节点集合变更时调整退出线位置
 | 
						||
            if (this.ActionElement is IContainerWithExitline container) container.AdjustExitlinePosition();
 | 
						||
        }
 | 
						||
 | 
						||
        protected virtual void ActionElement_PropertyChanged(object? sender, PropertyChangedEventArgs e)
 | 
						||
        {
 | 
						||
            switch (e.PropertyName)
 | 
						||
            {
 | 
						||
                //TODO:处理托管的IActionElement节点的属性变更
 | 
						||
                case nameof(IActionElement.InstantInfo):
 | 
						||
                    this.InstantInfo = this.ActionElement.InstantInfo;
 | 
						||
                    break;
 | 
						||
                case nameof(IContainerWithExitline.ExitlinePosition):
 | 
						||
                    // 自身退出线变更时调整所有子节点退出线位置
 | 
						||
                    (this.ActionElement as IContainerWithExitline)?.AdjustExitlinePosition();
 | 
						||
                    break;
 | 
						||
                default: break;
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        public void ReadyToWorking(IElement? element = null, Output? output = null)
 | 
						||
        {
 | 
						||
            if (this.ActionElement != element && element is IActionElement action) this.ActionElement = action;
 | 
						||
            if (this.WorkMode == WorkMode.Waiting) this.WorkMode = WorkMode.Preview;
 | 
						||
        }
 | 
						||
 | 
						||
        public void ReadyToEditing(Runtime runtime)
 | 
						||
        {
 | 
						||
            this.ReadyToWorking();
 | 
						||
            this.WorkMode = WorkMode.Editing;
 | 
						||
        }
 | 
						||
 | 
						||
        public void ReadyToRunning(Runtime runtime)
 | 
						||
        {
 | 
						||
            this.ReadyToWorking();
 | 
						||
            this.WorkMode = WorkMode.Running;
 | 
						||
        }
 | 
						||
        /// <summary>
 | 
						||
        /// 刷新视图样式
 | 
						||
        /// </summary>
 | 
						||
        protected virtual void RefreshViewerState(bool isOverMe = false)
 | 
						||
        {
 | 
						||
            if (this.IsDragging)
 | 
						||
            {
 | 
						||
                if (this.IsSelected)
 | 
						||
                {
 | 
						||
                    if (isOverMe) this.ViewerState = ViewerState.SelectedDragHover;
 | 
						||
                    else this.ViewerState = ViewerState.Selected;
 | 
						||
                }
 | 
						||
                else
 | 
						||
                {
 | 
						||
                    if (isOverMe) this.ViewerState = ViewerState.NormalDragHover;
 | 
						||
                    else this.ViewerState = ViewerState.Normal;
 | 
						||
                }
 | 
						||
            }
 | 
						||
            else
 | 
						||
            {
 | 
						||
                if (this.IsSelected)
 | 
						||
                {
 | 
						||
                    if (isOverMe) this.ViewerState = ViewerState.SelectedHover;
 | 
						||
                    else this.ViewerState = ViewerState.Selected;
 | 
						||
                }
 | 
						||
                else
 | 
						||
                {
 | 
						||
                    if (isOverMe) this.ViewerState = ViewerState.NormalHover;
 | 
						||
                    else this.ViewerState = ViewerState.Normal;
 | 
						||
                }
 | 
						||
            }
 | 
						||
        }
 | 
						||
        /// <summary>
 | 
						||
        /// 检查事件源是否需要自身处理
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="eventSource">引发事件的源</param>
 | 
						||
        /// <returns>只有事件源是自身,或事件源的第一个SmartView类型的祖辈是自身时才需要处理</returns>
 | 
						||
        protected virtual bool IsEventNeedToHandle(object eventSource)
 | 
						||
        {
 | 
						||
            bool result = false;
 | 
						||
            if (eventSource is ActionViewer view && view != this) result = false;
 | 
						||
            if (eventSource is not ActionViewer && eventSource is DependencyObject dobj && this == dobj.FindAncestor<ActionViewer>()) result = true;
 | 
						||
            return result;
 | 
						||
        }
 | 
						||
        protected virtual void RemoveDragAdorner()
 | 
						||
        { }
 | 
						||
        protected virtual void UpdateDragAdorner(Dock? dock)
 | 
						||
        { }
 | 
						||
        #region 交互事件
 | 
						||
        protected override void OnDragEnter(DragEventArgs e)
 | 
						||
        {
 | 
						||
            this.IsDragging = true;
 | 
						||
            ToolTipService.SetIsEnabled(this, false);
 | 
						||
 | 
						||
            base.OnDragEnter(e);
 | 
						||
        }
 | 
						||
        protected override void OnDragLeave(DragEventArgs e)
 | 
						||
        {
 | 
						||
            this.IsDragging = false;
 | 
						||
 | 
						||
            base.OnDragLeave(e);
 | 
						||
        }
 | 
						||
        protected internal bool _CanDropInParent = false;
 | 
						||
        protected internal bool _CanDropChild = false;
 | 
						||
        protected internal DropPlacement _DropPlacement = DropPlacement.Uncertain;
 | 
						||
        protected override void OnDragOver(DragEventArgs e)
 | 
						||
        {
 | 
						||
            if (this.IsEventNeedToHandle(e.OriginalSource))
 | 
						||
            {
 | 
						||
                this.RefreshViewerState(true);
 | 
						||
                FrameworkElement hitElement = this;
 | 
						||
                if (this.TitleContainer != null && this.TitleContainer.Visibility == Visibility.Visible)
 | 
						||
                    hitElement = this.TitleContainer;
 | 
						||
 | 
						||
                Point currentPoint = e.GetPosition(hitElement);
 | 
						||
                if (this._CanDropInParent && (currentPoint.Y < 10 || currentPoint.Y < 10))
 | 
						||
                {
 | 
						||
                    this._DropPlacement = DropPlacement.BeforeMe;
 | 
						||
                    this.UpdateDragAdorner(Dock.Top);
 | 
						||
                }
 | 
						||
                else if (this._CanDropInParent && (hitElement.ActualHeight - currentPoint.Y < 10 || hitElement.ActualWidth - currentPoint.X < 10))
 | 
						||
                {
 | 
						||
                    this._DropPlacement = DropPlacement.BehindMe;
 | 
						||
                    this.UpdateDragAdorner(Dock.Bottom);
 | 
						||
                }
 | 
						||
                else if (this._CanDropChild)
 | 
						||
                {
 | 
						||
                    this._DropPlacement = DropPlacement.WithinMe;
 | 
						||
                    this.UpdateDragAdorner(null);
 | 
						||
                }
 | 
						||
                else
 | 
						||
                {
 | 
						||
                    this._DropPlacement = DropPlacement.Rejected;
 | 
						||
                    this.RemoveDragAdorner();
 | 
						||
                }
 | 
						||
            }
 | 
						||
            else
 | 
						||
            {
 | 
						||
                this.RefreshViewerState();
 | 
						||
                this.RemoveDragAdorner();
 | 
						||
            }
 | 
						||
 | 
						||
            base.OnDragOver(e);
 | 
						||
        }
 | 
						||
        protected override void OnDrop(DragEventArgs e)
 | 
						||
        {
 | 
						||
            this.IsDragging = false;
 | 
						||
            this.RefreshViewerState();
 | 
						||
            this.RemoveDragAdorner();
 | 
						||
            if (this.IsEventNeedToHandle(e.OriginalSource))
 | 
						||
            {
 | 
						||
                //TODO:发送准备放置事件,如果事件被处理则「return」放弃默认逻辑
 | 
						||
                //注意:这里不能标记e.Handle=true;否则可能会造成视图显示状态异常
 | 
						||
                if (e.Data.GetData(typeof(DragDropData)) is DragDropData data)
 | 
						||
                {
 | 
						||
                    data.Placement = this._DropPlacement;
 | 
						||
                    //TODO:执行放置操作
 | 
						||
                }
 | 
						||
            }
 | 
						||
 | 
						||
            base.OnDrop(e);
 | 
						||
        }
 | 
						||
        protected override void OnMouseEnter(MouseEventArgs e)
 | 
						||
        {
 | 
						||
            base.OnMouseEnter(e);
 | 
						||
            ToolTipService.SetIsEnabled(this, true);
 | 
						||
            if (!this.IsDragging) this.RefreshViewerState(true);
 | 
						||
        }
 | 
						||
        protected override void OnMouseLeave(MouseEventArgs e)
 | 
						||
        {
 | 
						||
            base.OnMouseLeave(e);
 | 
						||
 | 
						||
            if (!this.IsDragging) this.RefreshViewerState();
 | 
						||
        }
 | 
						||
        protected override void OnMouseDown(MouseButtonEventArgs e)
 | 
						||
        {
 | 
						||
            base.OnMouseDown(e);
 | 
						||
 | 
						||
            if (e.LeftButton == MouseButtonState.Pressed)
 | 
						||
            {
 | 
						||
                this.IsSelected = this.IsSelectable;
 | 
						||
                if (this.IsDraggable) this._DragStartPoint = e.GetPosition(this);
 | 
						||
            }
 | 
						||
        }
 | 
						||
        protected override void OnMouseUp(MouseButtonEventArgs e)
 | 
						||
        {
 | 
						||
            base.OnMouseUp(e);
 | 
						||
 | 
						||
            this._DragStartPoint = null;
 | 
						||
        }
 | 
						||
        protected override void OnMouseMove(MouseEventArgs e)
 | 
						||
        {
 | 
						||
            base.OnMouseMove(e);
 | 
						||
            if (this.IsDragging) return;
 | 
						||
            bool isEventNeedHandle = this.IsEventNeedToHandle(e.OriginalSource);
 | 
						||
            this.RefreshViewerState(isEventNeedHandle);
 | 
						||
            if (isEventNeedHandle)
 | 
						||
            {
 | 
						||
                if (this.ActionElement == null || this.ActionElement.IsLockedElement) return;
 | 
						||
 | 
						||
                var position = e.GetPosition(this);
 | 
						||
                ToolTipService.SetPlacement(this, PlacementMode.Relative);
 | 
						||
                ToolTipService.SetPlacementTarget(this, this);
 | 
						||
                ToolTipService.SetHorizontalOffset(this, position.X + 16);
 | 
						||
                ToolTipService.SetVerticalOffset(this, position.Y + 16);
 | 
						||
            }
 | 
						||
        }
 | 
						||
        protected internal readonly object _DragLock = new();
 | 
						||
        protected internal Point? _DragStartPoint = null;
 | 
						||
 | 
						||
        protected override void OnPreviewMouseMove(MouseEventArgs e)
 | 
						||
        {
 | 
						||
            base.OnPreviewMouseMove(e);
 | 
						||
            if (!this.IsDraggable) return;
 | 
						||
            if (e.LeftButton == MouseButtonState.Pressed)
 | 
						||
            {
 | 
						||
                lock (_DragLock)
 | 
						||
                {
 | 
						||
                    if (this.IsDragging || !_DragStartPoint.HasValue) return;
 | 
						||
                    if (_DragStartPoint.HasValue)
 | 
						||
                    {
 | 
						||
                        Point currentPoint = e.GetPosition(this);
 | 
						||
 | 
						||
                        if (Math.Abs(this._DragStartPoint.Value.X - currentPoint.X) > SystemParameters.MinimumHorizontalDragDistance
 | 
						||
                            ||
 | 
						||
                            Math.Abs(this._DragStartPoint.Value.Y - currentPoint.Y) > SystemParameters.MinimumVerticalDragDistance)
 | 
						||
                        {
 | 
						||
                            //TODO:发送准备拖动事件,如果事件被响应则「return」退出原本逻辑
 | 
						||
 | 
						||
                            DragDropEffects dragDropEffects = DragDropEffects.Link;
 | 
						||
                            if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
 | 
						||
                                dragDropEffects |= DragDropEffects.Copy;
 | 
						||
                            else dragDropEffects |= DragDropEffects.Move;
 | 
						||
                            //TODO:构造拖动数据
 | 
						||
                            e.Handled = true;
 | 
						||
                            this._DragStartPoint = null;
 | 
						||
                            //TODO:启动拖动逻辑
 | 
						||
                            //DragDrop.DoDragDrop(this, data, data.dragEffect);
 | 
						||
                        }
 | 
						||
                    }
 | 
						||
                }
 | 
						||
            }
 | 
						||
        }
 | 
						||
        #endregion
 | 
						||
    }
 | 
						||
}
 |