using GongSolutions.Wpf.DragDrop; using GongSolutions.Wpf.DragDrop.Utilities; using HMI.Base; using HMI.UI; using Plugin.TestBuilder.Entity; using Plugin.TestBuilder.Model; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Data; namespace Plugin.TestBuilder { public class TestHandler : DefaultDropHandler { /// /// Test the specified drop information for the right data. /// /// The drop information. private bool CanDrop(IDropInfo dropInfo) { if (dropInfo?.DragInfo == null) { return false; } if (!dropInfo.IsSameDragDropContextAsSource) { return false; } // do not drop on itself var isTreeViewItem = dropInfo.InsertPosition.HasFlag(RelativeInsertPosition.TargetItemCenter) && dropInfo.VisualTargetItem is TreeViewItem; if (isTreeViewItem && dropInfo.VisualTargetItem == dropInfo.DragInfo.VisualSourceItem) { return false; } if (dropInfo.TargetCollection is null) { return false; } if (ReferenceEquals(dropInfo.DragInfo.SourceCollection, dropInfo.TargetCollection)) { var dragData = dropInfo.DragInfo?.Data as TreeItemData; var dropData = dropInfo.Data as TreeItemData; if (dragData == null || dropData == null) { return false; } if (dropData.ParentItem != dragData.ParentItem) { return false; } var targetList = dropInfo.TargetCollection.TryGetList(); return targetList != null; } if (TestCompatibleTypes(dropInfo.TargetCollection, dropInfo.Data)) { var isChildOf = IsChildOf(dropInfo.VisualTargetItem, dropInfo.DragInfo.VisualSourceItem); return !isChildOf; } return false; } public bool CanConvert(IDropInfo dropInfo) { bool InterfaceFilter(Type t, object o) => (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable<>)); Type[] enumerableInterfaces = dropInfo.TargetCollection.GetType().FindInterfaces(InterfaceFilter, null); var enumerableTypes = from i in enumerableInterfaces select i.GetGenericArguments().Single(); if (enumerableTypes.Any()) { Type dataType = TypeUtilities.GetCommonBaseClass(ExtractData(dropInfo.Data)); return dataType == typeof(FuncModel) && enumerableTypes.Any(t => t == typeof(Step)); } return false; } public Step ConvertFunc2Step(FuncModel func) { return new Step { Name = func.Name }; } public override void DragOver(IDropInfo dropInfo) { if (CanAcceptData(dropInfo)) { base.DragOver(dropInfo); } else if (CanConvert(dropInfo)) { // 固定Copy dropInfo.Effects = DragDropEffects.Copy; var isTreeViewItem = dropInfo.InsertPosition.HasFlag(RelativeInsertPosition.TargetItemCenter) && dropInfo.VisualTargetItem is TreeViewItem; dropInfo.DropTargetAdorner = isTreeViewItem ? DropTargetAdorners.Highlight : DropTargetAdorners.Insert; } } public override void Drop(IDropInfo dropInfo) { if (CanDrop(dropInfo)) { base.Drop(dropInfo); } else if (CanConvert(dropInfo)) { int insertIndex = GetInsertIndex(dropInfo); var destinationList = dropInfo.TargetCollection.TryGetList(); var data = ExtractData(dropInfo.Data).OfType().ToList(); if (destinationList != null) { var objects2Insert = new List(); foreach (var o in data) { var obj2Insert = ConvertFunc2Step(o as FuncModel); objects2Insert.Add(obj2Insert); destinationList.Insert(insertIndex++, obj2Insert); // 下方对象如果实现了 IDragItemSource 接口,会在这里调用 ItemDropped 方法,算是后置处理 if (obj2Insert is IDragItemSource dragItemSource) { dragItemSource.ItemDropped(dropInfo); } } SelectDroppedItems(dropInfo, objects2Insert); } } } } /// /// WorkControl.xaml 的交互逻辑 /// public partial class TestBuilder : PluginControl { public TestBuilder() { DataContext = this; InitializeComponent(); Loaded += UserControl_Loaded; } public IDropTarget dropHandler { get; set; } = new TestHandler(); private ObservableCollection datasource = new ObservableCollection() { new SeqData{ Name="test",Children = new ObservableCollection{ new SeqData{ Name="CCC"} } } }; public ObservableCollection Datasource { get => datasource; set { Set(ref datasource, value); } } private void Button_Click(object sender, RoutedEventArgs e) { Button btn = sender as Button; switch (btn.Name) { case "addBtn": Datasource.Add(new SeqData()); break; case "sda": DataGridRow s = (DataGridRow)btn.DataContext; SeqData data = s.Item as SeqData; data.Children.Add(new SeqData { Name = "CCC" }); s.DetailsVisibility = s.DetailsVisibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible; break; default: break; } } private void UserControl_Loaded(object sender, RoutedEventArgs e) { SizeChanged += WorkControl_SizeChanged; Loaded -= UserControl_Loaded; } /// /// 重设大小 /// /// /// private void WorkControl_SizeChanged(object sender, SizeChangedEventArgs e) { } /// /// 树数据展示过滤 /// /// /// private void CollectionViewSource_Filter(object sender, FilterEventArgs e) { if (e.Item is TreeItemData data) { e.Accepted = data.IsVisible; } } /// /// 树展开/关闭事件 /// /// /// private void treeDataGrid_ExpandedChange(object sender, bool e) { CollectionViewSource cvs = this.Resources["TreeGridFilter"] as CollectionViewSource; cvs?.View.Refresh(); } } }