WPF一个完整的TreeView使用实例:(二)拖拽改变父子节点层级

该博客详细介绍了如何在WPF的TreeView中实现拖拽功能,以改变父子节点的层级关系。通过添加全局变量、响应MouseLeftButtonDown事件以及在TreeViewItem样式中设置拖拽事件,实现了拖放操作。文章还提到了系列教程的其他部分,包括自定义样式、数据源绑定、动态添加节点、右键菜单功能以及节点重命名。
摘要由CSDN通过智能技术生成

本节主要在上节的基础上实现拖拽改变父子节点层级的功能,效果如下:

1、添加全局变量

private Point lastMouseDownPoint;//上一次鼠标左键点击位置
private TreeViewNode targetNode;//目标节点

2、在TreeView控件中加入MouseLeftButtonDown事件

        /// <summary>
        /// 鼠标左键按下事件响应
        /// </summary>
        private void TreeView_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ChangedButton == MouseButton.Left)
            {
                lastMouseDownPoint = e.GetPosition(this.treeView);
            }
        }

3、在TreeViewItem样式中加入拖拽相关事件

            <EventSetter Event="DragEnter" Handler="TreeView_DragEnter"></EventSetter>
            <EventSetter Event="DragLeave" Handler="TreeView_DragLeave"></EventSetter>
            <EventSetter Event="DragOver" Handler="TreeView_DragEnter"></EventSetter>
            <EventSetter Event="Drop" Handler="TreeView_Drop"></EventSetter>
            <EventSetter Event="MouseMove" Handler="TreeView_MouseMove"></EventSetter>

相关事件源码:

        /// <summary>
        /// 拖拽进入,改变字体颜色
        /// </summary>
        private void TreeView_DragEnter(object sender, DragEventArgs e)
        {
            TreeViewItem container = GetNearestContainer(e.OriginalSource as UIElement);
            if (container != null)
            {
                container.Foreground = new SolidColorBrush(Colors.Orange);
            }
        }

        /// <summary>
        /// 拖拽离
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
首先,我们需要在ViewModel中定义一个类来表示树节点,例如: ```csharp public class TreeNodeViewModel : INotifyPropertyChanged { private string _text; private ObservableCollection<TreeNodeViewModel> _children; public string Text { get { return _text; } set { if (_text != value) { _text = value; OnPropertyChanged(nameof(Text)); } } } public ObservableCollection<TreeNodeViewModel> Children { get { return _children; } set { if (_children != value) { _children = value; OnPropertyChanged(nameof(Children)); } } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } ``` 然后,我们在MainViewModel中定义一个ObservableCollection<TreeNodeViewModel>来表示树的根节点,以及一些方法来添加/删除节点和处理双击事件: ```csharp public class MainViewModel : INotifyPropertyChanged { private ObservableCollection<TreeNodeViewModel> _rootNodes; public ObservableCollection<TreeNodeViewModel> RootNodes { get { return _rootNodes; } set { if (_rootNodes != value) { _rootNodes = value; OnPropertyChanged(nameof(RootNodes)); } } } public MainViewModel() { RootNodes = new ObservableCollection<TreeNodeViewModel>(); } public void AddNode(TreeNodeViewModel parent, string text) { if (parent == null) { RootNodes.Add(new TreeNodeViewModel { Text = text, Children = new ObservableCollection<TreeNodeViewModel>() }); } else { parent.Children.Add(new TreeNodeViewModel { Text = text, Children = new ObservableCollection<TreeNodeViewModel>() }); } } public void RemoveNode(TreeNodeViewModel node) { if (node == null) { return; } if (node == RootNodes.FirstOrDefault()) { RootNodes.Remove(node); } else { var parent = FindParentNode(RootNodes, node); if (parent != null) { parent.Children.Remove(node); } } } public void HandleDoubleClick(TreeNodeViewModel node) { // handle double click event } private TreeNodeViewModel FindParentNode(IEnumerable<TreeNodeViewModel> nodes, TreeNodeViewModel child) { foreach (var node in nodes) { if (node == child || node.Children == null) { continue; } if (node.Children.Contains(child)) { return node; } var parent = FindParentNode(node.Children, child); if (parent != null) { return parent; } } return null; } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } ``` 最后,我们可以在View使用TreeView控件来显示树,并将其绑定到MainViewModel中的RootNodes属性。我们还可以为TreeViewItem添加双击事件处理程序,以及为ContextMenu添加添加/删除节点的菜单项。 ```xaml <TreeView ItemsSource="{Binding RootNodes}"> <TreeView.ItemTemplate> <HierarchicalDataTemplate ItemsSource="{Binding Children}"> <TextBlock Text="{Binding Text}" /> </HierarchicalDataTemplate> </TreeView.ItemTemplate> <TreeView.ItemContainerStyle> <Style TargetType="{x:Type TreeViewItem}"> <EventSetter Event="MouseDoubleClick" Handler="TreeViewItem_DoubleClick" /> <Setter Property="ContextMenu"> <Setter.Value> <ContextMenu> <MenuItem Header="Add Node" Command="{Binding AddNodeCommand}" /> <MenuItem Header="Remove Node" Command="{Binding RemoveNodeCommand}" /> </ContextMenu> </Setter.Value> </Setter> </Style> </TreeView.ItemContainerStyle> </TreeView> ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RunnerDNA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值