chr
2024-03-01 8d344c1b64a4b88fa78a46c0825f5d71c557a815
优化DataGridUI;完善拖拽;
11个文件已修改
3个文件已添加
851 ■■■■■ 已修改文件
Controls/InnerWindow.xaml 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Models/FuncModel.cs 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Style/Colors.xaml 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Style/CommonTree.xaml 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI/Test/FunctionSetting.xaml 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI/Test/FunctionSetting.xaml.cs 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI/Test/ProgramList.xaml 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI/Test/ProgramList.xaml.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI/Test/SequnceList.xaml 314 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
UI/Test/SequnceList.xaml.cs 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Utils/DdDragHandler.cs 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Utils/DdDropHandler.cs 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WPFProject.csproj 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packages.config 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Controls/InnerWindow.xaml
@@ -4,6 +4,7 @@
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WPFProject.Controls"
             mc:Ignorable="d" 
             HorizontalAlignment="Stretch"
             HorizontalContentAlignment="Stretch"
Models/FuncModel.cs
New file
@@ -0,0 +1,24 @@
using System.Collections.ObjectModel;
namespace WPFProject.Models
{
    public class FuncModel : NotifyBase
    {
        private string _Name;
        public string Name
        {
            get { return _Name; }
            set => RaiseAndSetIfChanged(ref _Name, value);
        }
        private ObservableCollection<FuncModel> _Children;
        public ObservableCollection<FuncModel> Children
        {
            get { return _Children; }
            set => RaiseAndSetIfChanged(ref _Children, value);
        }
    }
}
Style/Colors.xaml
@@ -7,6 +7,7 @@
    <Brush x:Key="SecondaryImportant">Orange</Brush>
    <Brush x:Key="Important">#e17933</Brush>
    <Brush x:Key="ImportantFont">#FFF</Brush>
    <Brush x:Key="ButtonColor">#103156</Brush>
Style/CommonTree.xaml
@@ -1,13 +1,13 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    
             xmlns:hc="https://handyorg.github.io/handycontrol"
                    >
             xmlns:hc="https://handyorg.github.io/handycontrol"
                    >
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml"/>
        <ResourceDictionary Source="/WPFProject;component/Style/colors.xaml"/>
    </ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml"/>
        <ResourceDictionary Source="/WPFProject;component/Style/colors.xaml"/>
    </ResourceDictionary.MergedDictionaries>
    <Style TargetType="TreeViewItem" BasedOn="{StaticResource TreeViewItemBaseStyle}">
        <Setter Property="Template">
            <Setter.Value>
@@ -47,5 +47,5 @@
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    </Style>
</ResourceDictionary>
UI/Test/FunctionSetting.xaml
@@ -4,6 +4,10 @@
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WPFProject.UI.Test"
             xmlns:dd="urn:gong-wpf-dragdrop"
             xmlns:m="clr-namespace:WPFProject.Models"
             xmlns:util="clr-namespace:WPFProject.Utils"
             xmlns:hc="https://handyorg.github.io/handycontrol"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
@@ -19,41 +23,29 @@
            <Style TargetType="Label"/>
            <Style TargetType="TabControl"/>
            <Style TargetType="TreeView">
            </Style>
        </ResourceDictionary>
    </UserControl.Resources>
    <Grid>
        <TabControl Style="{StaticResource ControlStyle}">
            <TabItem Header="函数列表">
                <StackPanel>
                    <hc:SearchBar hc:InfoElement.Placeholder="输入文本查询"  Style="{StaticResource SearchBarPlus}" Margin="10,5,10,5"/>
                    <TreeView BorderThickness="0" >
                        <TreeViewItem Header="111">
                            <TreeViewItem Header="111">
                                <TreeViewItem Header="999"/>
                            </TreeViewItem>
                            <TreeViewItem Header="222"/>
                            <TreeViewItem Header="333"/>
                        </TreeViewItem>
                        <TreeViewItem Header="222">
                            <TreeViewItem Header="111"/>
                            <TreeViewItem Header="222"/>
                            <TreeViewItem Header="333"/>
                        </TreeViewItem>
                    <TreeView BorderThickness="0" ItemsSource="{Binding FuncModels}"
                              dd:DragDrop.IsDragSource="True"
                                dd:DragDrop.ShowAlwaysDropTargetAdorner="True"
                                dd:DragDrop.UseDefaultDragAdorner="True"
                                dd:DragDrop.DragHandler="{Binding dragHandler}"
                              >
                        <TreeView.ItemTemplate>
                            <HierarchicalDataTemplate DataType="{x:Type m:FuncModel}" ItemsSource="{Binding Path=Children}">
                                <ContentControl Content="{Binding Name}"/>
                            </HierarchicalDataTemplate>
                        </TreeView.ItemTemplate>
                    </TreeView>
                </StackPanel>
            </TabItem>
            <TabItem Header="变量列表">
            </TabItem>
UI/Test/FunctionSetting.xaml.cs
@@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
@@ -12,17 +15,65 @@
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WPFProject.Models;
using WPFProject.Utils;
namespace WPFProject.UI.Test
{
    /// <summary>
    /// FunctionSetting.xaml 的交互逻辑
    /// </summary>
    public partial class FunctionSetting : UserControl
    {
    public partial class FunctionSetting : UserControl, INotifyPropertyChanged
    {
        public virtual event PropertyChangedEventHandler PropertyChanged;
        protected virtual void RaisePropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
        protected void RaiseAndSetIfChanged<T>(ref T old, T @new, [CallerMemberName] string propertyName = null)
        {
            old = @new;
            if (propertyName != null)
            {
                RaisePropertyChanged(propertyName);
            }
        }
        public FunctionSetting()
        {
            DataContext = this;
            InitializeComponent();
        }
        public DdDragHandler dragHandler { get; set; } = new DdDragHandler();
        private ObservableCollection<FuncModel> _FuncModels = new ObservableCollection<FuncModel>() {
            new FuncModel(){
                Name = "111",
                Children = new ObservableCollection<FuncModel>(){
                    new FuncModel(){ Name = "1123"},
                    new FuncModel(){ Name = "1223"},
                }
            },
            new FuncModel()
            {
                Name = "222",
                Children = new ObservableCollection<FuncModel>(){
                    new FuncModel(){ Name = "2123"},
                    new FuncModel(){ Name = "2223"},
                }
            }
        };
        public ObservableCollection<FuncModel> FuncModels
        {
            get { return _FuncModels; }
            set => RaiseAndSetIfChanged(ref _FuncModels, value);
        }
    }
}
UI/Test/ProgramList.xaml
@@ -1,33 +1,39 @@
<UserControl x:Class="WPFProject.UI.Test.ProgramList"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:WPFProject.UI.Test"
             xmlns:vm="clr-namespace:WPFProject.ViewModels"
             mc:Ignorable="d"
             HorizontalAlignment="Stretch"
             HorizontalContentAlignment="Stretch"
             Background="#FFF" >
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/WPFProject;component/Style/ListViewStyle.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            <Style TargetType="Label"></Style>
        </ResourceDictionary>
    </UserControl.Resources>
    <Grid>
        <ListView ItemsSource="{Binding Programs}" ItemContainerStyle="{StaticResource a}"
                  VerticalContentAlignment="Center"
                  SelectionChanged="ListView_SelectionChanged">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ContentControl Content="{Binding Name}"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</UserControl>
<UserControl x:Class="WPFProject.UI.Test.ProgramList"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:WPFProject.UI.Test"
             xmlns:vm="clr-namespace:WPFProject.ViewModels"
             xmlns:dd="urn:gong-wpf-dragdrop"
             mc:Ignorable="d"
             HorizontalAlignment="Stretch"
             HorizontalContentAlignment="Stretch"
             Background="#FFF" >
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/WPFProject;component/Style/ListViewStyle.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            <Style TargetType="Label"></Style>
        </ResourceDictionary>
    </UserControl.Resources>
    <Grid>
        <ListView ItemsSource="{Binding Programs}" ItemContainerStyle="{StaticResource a}"
                  VerticalContentAlignment="Center"
                  dd:DragDrop.IsDragSource="True"
                  dd:DragDrop.IsDropTarget="True"
                  dd:DragDrop.ShowAlwaysDropTargetAdorner="True"
                  dd:DragDrop.UseDefaultDragAdorner="True"
                  SelectionChanged="ListView_SelectionChanged">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ContentControl Content="{Binding Name}"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</UserControl>
UI/Test/ProgramList.xaml.cs
@@ -73,7 +73,10 @@
        private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ProgramChanged?.Invoke(this, e.AddedItems[0] as Program);
            if (e.AddedItems.Count > 0)
            {
                ProgramChanged?.Invoke(this, e.AddedItems[0] as Program);
            }
        }
    }
}
UI/Test/SequnceList.xaml
@@ -1,87 +1,227 @@
<UserControl x:Class="WPFProject.UI.Test.SequnceList"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:WPFProject.UI.Test"
             mc:Ignorable="d"
             Background="#FFF"
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml"/>
                <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml"/>
                <ResourceDictionary Source="/WPFProject;component/Style/colors.xaml"/>
                <ResourceDictionary Source="/WPFProject;component/Style/WindowResources.xaml"/>
                <ResourceDictionary Source="/WPFProject;component/Style/ListViewStyle.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            <Style TargetType="Label"></Style>
            <Style TargetType="ListView"></Style>
            <Color x:Key="DarkPrimaryColor">#e17933</Color>
            <Color x:Key="PrimaryColor">#e17933</Color>
        </ResourceDictionary>
    </UserControl.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="3*"/>
            <ColumnDefinition Width="2"/>
            <ColumnDefinition Width="7*"/>
        </Grid.ColumnDefinitions>
        <ListView ItemContainerStyle="{StaticResource a}" ItemsSource="{Binding Sequences}" BorderThickness="0">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ContentControl Content="{Binding Name}"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <GridSplitter Grid.Column="1" Background="LightGray" HorizontalAlignment="Center" Width="2" ResizeDirection="Columns"/>
        <Grid Grid.Column="2">
            <Grid.RowDefinitions>
                <RowDefinition Height="30"/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Label Content="测试流程" VerticalContentAlignment="Center"/>
            <DataGrid x:Name="dataGrid" AutoGenerateColumns="False" FrozenColumnCount="1" Background="#FFF" Grid.Row="1"
                      BorderThickness="0"
                      ItemsSource="{Binding Steps}">
                <DataGrid.Columns>
                    <DataGridTextColumn IsReadOnly="True" Width="80" CanUserResize="False" Binding="{Binding Index}" Header="序号"/>
                    <DataGridTextColumn Header="标题1" Binding="{Binding Name}"></DataGridTextColumn>
                    <DataGridTextColumn Header="标题2" Binding="{Binding Name}"></DataGridTextColumn>
                    <DataGridTextColumn Header="标题3" Binding="{Binding Name}"></DataGridTextColumn>
                    <DataGridTextColumn Header="标题4" Binding="{Binding Name}"></DataGridTextColumn>
                    <DataGridTemplateColumn x:Name="opt" Width="120" CanUserResize="False" Header="操作">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal">
                                    <Button Style="{StaticResource LinkButton}" Margin="0,0,20,0">123</Button>
                                    <Button Style="{StaticResource LinkButton}">删除</Button>
                                </StackPanel>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>
            <!--<ListView >
                <ListView.View>
                    <GridView>
                    </GridView>
                </ListView.View>
            </ListView>-->
        </Grid>
    </Grid>
</UserControl>
<UserControl x:Class="WPFProject.UI.Test.SequnceList"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:WPFProject.UI.Test"
             xmlns:hc="https://handyorg.github.io/handycontrol"
             xmlns:dd="urn:gong-wpf-dragdrop"
             mc:Ignorable="d"
             Background="#FFF"
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml"/>
                <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml"/>
                <ResourceDictionary Source="/WPFProject;component/Style/colors.xaml"/>
                <ResourceDictionary Source="/WPFProject;component/Style/WindowResources.xaml"/>
                <ResourceDictionary Source="/WPFProject;component/Style/ListViewStyle.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            <Style TargetType="Label"></Style>
            <Style TargetType="ListView"></Style>
            <Style TargetType="DataGridRow" x:Key="CommonRow" BasedOn="{StaticResource DataGridRowStyle}">
                <Setter Property="Margin" Value="0"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="DataGridRow">
                            <SelectiveScrollingGrid>
                                <SelectiveScrollingGrid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="*"/>
                                </SelectiveScrollingGrid.ColumnDefinitions>
                                <SelectiveScrollingGrid.RowDefinitions>
                                    <RowDefinition Height="*"/>
                                    <RowDefinition Height="Auto"/>
                                </SelectiveScrollingGrid.RowDefinitions>
                                <Border Grid.ColumnSpan="2" x:Name="DGR_Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"/>
                                <DataGridCellsPresenter MinHeight="{TemplateBinding MinHeight}" VerticalContentAlignment="Center" Grid.Row="0" Grid.Column="1" ItemsPanel="{TemplateBinding ItemsPanel}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                <DataGridDetailsPresenter Grid.Column="1" Grid.Row="1" SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, RelativeSource={RelativeSource AncestorType=DataGrid}}" Visibility="{TemplateBinding DetailsVisibility}"/>
                                <DataGridRowHeader Grid.Row="0" Grid.Column="0" SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Row}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
                            </SelectiveScrollingGrid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter Property="Background" Value="{StaticResource SecondaryImportant}"/>
                    </Trigger>
                    <Trigger Property="IsSelected" Value="True">
                        <Setter Property="Background" Value="{StaticResource Important}"/>
                        <Setter Property="TextElement.Foreground" Value="#FFF"/>
                    </Trigger>
                    <!--<MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsSelected" Value="true"/>
                            <Condition Property="Selector.IsSelectionActive" Value="false"/>
                        </MultiTrigger.Conditions>
                        <Setter Property="Background" Value="{DynamicResource DarkDefaultBrush}"/>
                        <Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
                    </MultiTrigger>-->
                </Style.Triggers>
            </Style>
            <Style TargetType="DataGridColumnHeader" x:Key="CommonColumnHeader">
                <Setter Property="BorderBrush" Value="{Binding Path=HorizontalGridLinesBrush,RelativeSource={RelativeSource FindAncestor,AncestorType=DataGrid}}"/>
                <Setter Property="BorderThickness" Value="0,1,1,1"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Column.DisplayIndex}" Value="0">
                        <Setter Property="BorderThickness" Value="1,1,1,1"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
            <Style TargetType="DataGridCell" x:Key="CommonCell" BasedOn="{StaticResource DataGridCellStyle}">
                <Setter Property="BorderBrush" Value="{Binding Path=HorizontalGridLinesBrush,RelativeSource={RelativeSource FindAncestor,AncestorType=DataGrid}}"/>
                <Setter Property="BorderThickness" Value="0,0,1,1"/>
                <Setter Property="Padding" Value="0"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="DataGridCell">
                            <Border Padding="{TemplateBinding Padding}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                                <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Column.DisplayIndex}" Value="0">
                        <Setter Property="BorderThickness" Value="1,0,1,1"/>
                    </DataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding IsSelected,RelativeSource={RelativeSource Self}}" Value="true"/>
                            <Condition Binding="{Binding SelectionUnit,RelativeSource={RelativeSource FindAncestor,AncestorType=DataGrid}}" Value="Cell"/>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Foreground" Value="{StaticResource ImportantFont}"/>
                        <Setter Property="Background" Value="{StaticResource Important}"/>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding IsSelected,RelativeSource={RelativeSource Self}}" Value="true"/>
                            <Condition Binding="{Binding IsSelected,RelativeSource={RelativeSource AncestorType=DataGridRow}}" Value="False"/>
                            <Condition Binding="{Binding SelectionUnit,RelativeSource={RelativeSource FindAncestor,AncestorType=DataGrid}}" Value="CellOrRowHeader"/>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Foreground" Value="{StaticResource ImportantFont}"/>
                        <Setter Property="Background" Value="{StaticResource Important}"/>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding IsSelected,RelativeSource={RelativeSource Self}}" Value="true"/>
                            <Condition Binding="{Binding IsSelected,RelativeSource={RelativeSource AncestorType=DataGridRow}}" Value="True"/>
                            <Condition Binding="{Binding SelectionUnit,RelativeSource={RelativeSource FindAncestor,AncestorType=DataGrid}}" Value="CellOrRowHeader"/>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Foreground" Value="{StaticResource ImportantFont}"/>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding IsSelected,RelativeSource={RelativeSource Self}}" Value="true"/>
                            <Condition Binding="{Binding SelectionUnit,RelativeSource={RelativeSource FindAncestor,AncestorType=DataGrid}}" Value="FullRow"/>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Foreground" Value="{StaticResource ImportantFont}"/>
                    </MultiDataTrigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsSelected" Value="true"/>
                            <Condition Property="Selector.IsSelectionActive" Value="false"/>
                        </MultiTrigger.Conditions>
                        <Setter Property="Foreground" Value="{StaticResource ImportantFont}"/>
                        <Setter Property="Background" Value="{StaticResource Important}"/>
                    </MultiTrigger>
                </Style.Triggers>
            </Style>
            <Style TargetType="DataGrid" BasedOn="{StaticResource DataGridBaseStyle}">
                <Setter Property="GridLinesVisibility" Value="None"/>
                <Setter Property="HorizontalGridLinesBrush" Value="Gray"/>
                <Setter Property="RowStyle" Value="{StaticResource CommonRow}"/>
                <Setter Property="CellStyle" Value="{StaticResource CommonCell}"/>
                <Setter Property="ColumnHeaderStyle" Value="{StaticResource CommonColumnHeader}"/>
                <Setter Property="hc:BorderElement.CornerRadius" Value="0" />
                <Setter Property="RowHeight" Value="30"/>
            </Style>
        </ResourceDictionary>
    </UserControl.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="3*"/>
            <ColumnDefinition Width="2"/>
            <ColumnDefinition Width="7*"/>
        </Grid.ColumnDefinitions>
        <ListView ItemContainerStyle="{StaticResource a}" ItemsSource="{Binding Sequences}" BorderThickness="0"
                  dd:DragDrop.IsDragSource="True"
                    dd:DragDrop.IsDropTarget="True"
                    dd:DragDrop.ShowAlwaysDropTargetAdorner="True"
                    dd:DragDrop.UseDefaultDragAdorner="True"
                  SelectionChanged="ListView_SelectionChanged">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ContentControl Content="{Binding Name}"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <GridSplitter Grid.Column="1" Background="LightGray" HorizontalAlignment="Center" Width="2" ResizeDirection="Columns"/>
        <Grid Grid.Column="2">
            <Grid.RowDefinitions>
                <RowDefinition Height="30"/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Label Content="测试流程" VerticalContentAlignment="Center"/>
            <DataGrid x:Name="dataGrid" AutoGenerateColumns="False"
                      CanUserAddRows="False"
                      CanUserSortColumns="False"
                      FrozenColumnCount="1" Background="#FFF" Grid.Row="1"
                      BorderThickness="0"
                      dd:DragDrop.IsDragSource="True"
                      dd:DragDrop.IsDropTarget="True"
                      dd:DragDrop.ShowAlwaysDropTargetAdorner="True"
                      dd:DragDrop.UseDefaultDragAdorner="True"
                      dd:DragDrop.SelectDroppedItems="True"
                      dd:DragDrop.DropHandler="{Binding dropHandler}"
                      ItemsSource="{Binding Steps}">
                <DataGrid.Columns>
                    <DataGridTextColumn IsReadOnly="True" Binding="{Binding Index}" Header="序号"/>
                    <DataGridTextColumn Header="标题1" Binding="{Binding Name}"></DataGridTextColumn>
                    <DataGridTextColumn Header="标题2" Binding="{Binding Name}"></DataGridTextColumn>
                    <DataGridTextColumn Header="标题3" Binding="{Binding Name}"></DataGridTextColumn>
                    <DataGridTextColumn Header="标题4" Binding="{Binding Name}"></DataGridTextColumn>
                    <DataGridTemplateColumn x:Name="opt" Width="*" Header="操作">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal">
                                    <Button Style="{StaticResource LinkButton}" Margin="0,0,20,0">123</Button>
                                    <Button Style="{StaticResource LinkButton}">删除</Button>
                                </StackPanel>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>
            <!--<ListView >
                <ListView.View>
                    <GridView>
                    </GridView>
                </ListView.View>
            </ListView>-->
        </Grid>
    </Grid>
</UserControl>
UI/Test/SequnceList.xaml.cs
@@ -1,77 +1,97 @@
using AIStudio.Wpf.Controls;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Controls;
using WPFProject.Models;
namespace WPFProject.UI.Test
{
    /// <summary>
    /// SequnceList.xaml 的交互逻辑
    /// </summary>
    public partial class SequnceList : UserControl, INotifyPropertyChanged
    {
        public virtual event PropertyChangedEventHandler PropertyChanged;
        protected virtual void RaisePropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
        protected void RaiseAndSetIfChanged<T>(ref T old, T @new, [CallerMemberName] string propertyName = null)
        {
            old = @new;
            if (propertyName != null)
            {
                RaisePropertyChanged(propertyName);
            }
        }
        public SequnceList()
        {
            DataContext = this;
            Sequences = new ObservableCollection<Sequence>
            {
                new Sequence{ Name="SSSSS"},
                new Sequence{ Name="SSSSS2"},
            };
            Steps = Sequences[0].Steps;
            InitializeComponent();
        }
        private ObservableCollection<Sequence> _Sequences;
        public ObservableCollection<Sequence> Sequences
        {
            get => _Sequences;
            set
            {
                if (value != null && value.Count > 0)
                {
                    Steps = value[0].Steps;
                }
                else {
                    Steps = null;
                }
                RaiseAndSetIfChanged(ref _Sequences, value);
            }
        }
        private ObservableCollection<Step> _Steps;
        public ObservableCollection<Step> Steps
        {
            get => _Steps;
            set => RaiseAndSetIfChanged(ref _Steps, value);
        }
        public void Selected_Program_Changed(object sender, Program program)
        {
            this.Sequences = program.Sequences;
        }
    }
}
using AIStudio.Wpf.Controls;
using GongSolutions.Wpf.DragDrop;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Controls;
using WPFProject.Models;
using WPFProject.Utils;
namespace WPFProject.UI.Test
{
    /// <summary>
    /// SequnceList.xaml 的交互逻辑
    /// </summary>
    public partial class SequnceList : UserControl, INotifyPropertyChanged
    {
        public virtual event PropertyChangedEventHandler PropertyChanged;
        protected virtual void RaisePropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
        protected void RaiseAndSetIfChanged<T>(ref T old, T @new, [CallerMemberName] string propertyName = null)
        {
            old = @new;
            if (propertyName != null)
            {
                RaisePropertyChanged(propertyName);
            }
        }
        public SequnceList()
        {
            DataContext = this;
            Sequences = new ObservableCollection<Sequence>
            {
                new Sequence{ Name="SSSSS"},
                new Sequence{ Name="SSSSS2"},
            };
            Steps = Sequences[0].Steps;
            InitializeComponent();
        }
        private ObservableCollection<Program> _ps = new ObservableCollection<Program>();
        public ObservableCollection<Program> Ps
        {
            get => _ps;
            set => RaiseAndSetIfChanged(ref _ps, value);
        }
        private ObservableCollection<Sequence> _Sequences;
        public ObservableCollection<Sequence> Sequences
        {
            get => _Sequences;
            set
            {
                if (value != null && value.Count > 0)
                {
                    Steps = value[0].Steps;
                }
                else {
                    Steps = null;
                }
                RaiseAndSetIfChanged(ref _Sequences, value);
            }
        }
        private ObservableCollection<Step> _Steps;
        public ObservableCollection<Step> Steps
        {
            get => _Steps;
            set => RaiseAndSetIfChanged(ref _Steps, value);
        }
        public void Selected_Program_Changed(object sender, Program program)
        {
            this.Sequences = program.Sequences;
        }
        private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count > 0)
            {
                Steps = (e.AddedItems[0] as Sequence).Steps;
            }
        }
        public IDropTarget dropHandler { get; set; } = new DdDropHandler();
    }
}
Utils/DdDragHandler.cs
New file
@@ -0,0 +1,20 @@
using GongSolutions.Wpf.DragDrop;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using WPFProject.Models;
namespace WPFProject.Utils
{
    public class DdDragHandler : DefaultDragHandler
    {
        public override bool CanStartDrag(IDragInfo dragInfo)
        {
            FuncModel model = dragInfo.SourceItem as FuncModel;
            return model.Children ==null || model.Children.Count == 0;
        }
    }
}
Utils/DdDropHandler.cs
New file
@@ -0,0 +1,94 @@
using GongSolutions.Wpf.DragDrop;
using GongSolutions.Wpf.DragDrop.Utilities;
using System.Collections.Generic;
using System.ComponentModel;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Linq;
using System.Collections;
using WPFProject.Models;
namespace WPFProject.Utils
{
    public class DdDropHandler : DefaultDropHandler
    {
        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 (CanAcceptData(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);
                }
            }
        }
    }
}
WPFProject.csproj
@@ -39,6 +39,9 @@
    <Reference Include="AIStudio.Wpf.Controls, Version=1.2.2.0, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>packages\AIStudio.Wpf.Controls.1.2.2\lib\net461\AIStudio.Wpf.Controls.dll</HintPath>
    </Reference>
    <Reference Include="GongSolutions.WPF.DragDrop, Version=3.0.0.0, Culture=neutral, PublicKeyToken=91f1945125b7a587, processorArchitecture=MSIL">
      <HintPath>packages\gong-wpf-dragdrop.3.2.1\lib\net47\GongSolutions.WPF.DragDrop.dll</HintPath>
    </Reference>
    <Reference Include="HandyControl, Version=3.4.0.0, Culture=neutral, PublicKeyToken=45be8712787a1e5b, processorArchitecture=MSIL">
      <HintPath>packages\HandyControl.3.4.0\lib\net472\HandyControl.dll</HintPath>
    </Reference>
@@ -129,6 +132,7 @@
      <DependentUpon>Form1.cs</DependentUpon>
    </Compile>
    <Compile Include="Models\CanvasPosition.cs" />
    <Compile Include="Models\FuncModel.cs" />
    <Compile Include="Models\NotifyBase.cs" />
    <Compile Include="Models\Program.cs" />
    <Compile Include="Models\Sequence.cs" />
@@ -158,6 +162,8 @@
      <DependentUpon>WorkWindow.xaml</DependentUpon>
    </Compile>
    <Compile Include="Utils\CanvasHelper.cs" />
    <Compile Include="Utils\DdDragHandler.cs" />
    <Compile Include="Utils\DdDropHandler.cs" />
    <Compile Include="Utils\IPlugin.cs" />
    <Compile Include="Utils\Resize.cs" />
    <Compile Include="Utils\Win32Helper.cs" />
packages.config
@@ -1,15 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="AIStudio.Wpf.Controls" version="1.2.2" targetFramework="net472" />
  <package id="HandyControl" version="3.4.0" targetFramework="net472" />
  <package id="Microsoft.Xaml.Behaviors.Wpf" version="1.1.39" targetFramework="net472" />
  <package id="Newtonsoft.Json" version="13.0.1" targetFramework="net472" />
  <package id="System.IO" version="4.3.0" targetFramework="net472" />
  <package id="System.Net.Http" version="4.3.4" targetFramework="net472" />
  <package id="System.Runtime" version="4.3.0" targetFramework="net472" />
  <package id="System.Security.Cryptography.Algorithms" version="4.3.0" targetFramework="net472" />
  <package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net472" />
  <package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net472" />
  <package id="System.Security.Cryptography.X509Certificates" version="4.3.0" targetFramework="net472" />
  <package id="WPF.MDI" version="1.1.4" targetFramework="net472" />
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="AIStudio.Wpf.Controls" version="1.2.2" targetFramework="net472" />
  <package id="gong-wpf-dragdrop" version="3.2.1" targetFramework="net472" />
  <package id="HandyControl" version="3.4.0" targetFramework="net472" />
  <package id="Microsoft.Xaml.Behaviors.Wpf" version="1.1.39" targetFramework="net472" />
  <package id="Newtonsoft.Json" version="13.0.1" targetFramework="net472" />
  <package id="System.IO" version="4.3.0" targetFramework="net472" />
  <package id="System.Net.Http" version="4.3.4" targetFramework="net472" />
  <package id="System.Runtime" version="4.3.0" targetFramework="net472" />
  <package id="System.Security.Cryptography.Algorithms" version="4.3.0" targetFramework="net472" />
  <package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net472" />
  <package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net472" />
  <package id="System.Security.Cryptography.X509Certificates" version="4.3.0" targetFramework="net472" />
  <package id="WPF.MDI" version="1.1.4" targetFramework="net472" />
</packages>