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
|
{
|
/// <summary>
|
/// Test the specified drop information for the right data.
|
/// </summary>
|
/// <param name="dropInfo">The drop information.</param>
|
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<object>().ToList();
|
|
if (destinationList != null)
|
{
|
var objects2Insert = new List<object>();
|
|
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);
|
}
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
/// WorkControl.xaml 的交互逻辑
|
/// </summary>
|
public partial class TestBuilder : PluginControl
|
{
|
public TestBuilder()
|
{
|
DataContext = this;
|
InitializeComponent();
|
Loaded += UserControl_Loaded;
|
}
|
public IDropTarget dropHandler { get; set; } = new TestHandler();
|
|
private ObservableCollection<SeqData> datasource = new ObservableCollection<SeqData>() {
|
new SeqData{ Name="test",Children = new ObservableCollection<SeqData>{
|
new SeqData{ Name="CCC"}
|
} }
|
};
|
|
public ObservableCollection<SeqData> 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;
|
}
|
|
/// <summary>
|
/// 重设大小
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void WorkControl_SizeChanged(object sender, SizeChangedEventArgs e)
|
{
|
|
}
|
|
/// <summary>
|
/// 树数据展示过滤
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void CollectionViewSource_Filter(object sender, FilterEventArgs e)
|
{
|
if (e.Item is TreeItemData data)
|
{
|
e.Accepted = data.IsVisible;
|
}
|
}
|
|
/// <summary>
|
/// 树展开/关闭事件
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void treeDataGrid_ExpandedChange(object sender, bool e)
|
{
|
CollectionViewSource cvs = this.Resources["TreeGridFilter"] as CollectionViewSource;
|
cvs?.View.Refresh();
|
}
|
}
|
}
|