分享

日志

 泉水930 2013-01-10
WPF实现TreeView项的拖动及右键菜单
项目需求背景,用一个TreeView控件实现一个部门的层级显示,当需要把一个部门移动到另一个部门时,我们只需要把部门按层级展开,把源部门拖动到目标部门,然后根据需要的功能实现相应的鼠标右键功能。
 1、创建一个部门类Department
public class Department
    {
        public int ID { get; set; }
        public int ParentID { get; set; }
        public string Name { get; set; }
        public List<Department> Departments;
 
        public Department(int id, int parentid, string name)
        {
            ID = id;
            ParentID = parentid;
            Name = name;
            Departments = new List<Department>();
        }
    } 
2、一个公共方法类 CommanClass
    public class CommanClass
    {
        public List<Department> DepartmentCollection; 
        public CommanClass()
        {
            DepartmentCollection = CreateOrignDepartments();
        }
 
        public List<Department> CreateOrignDepartments()
        {
            List<Department> departs = new List<Department>();
            departs.Add(new Department(1, 0, "大学"));
            departs.Add(new Department(2, 1, "理学院"));
            departs.Add(new Department(3, 1, "工学院"));
            departs.Add(new Department(4, 1, "文学院"));
            departs.Add(new Department(5, 2, "数学系"));
            departs.Add(new Department(6, 2, "物理系"));
            departs.Add(new Department(7, 3, "机械工程系"));
            departs.Add(new Department(8, 3, "土木工程系"));
            departs.Add(new Department(9, 3, "电子自动化系"));
            departs.Add(new Department(10, 4, "外语系"));
            departs.Add(new Department(11, 4, "古文学系"));
            departs.Add(new Department(12, 4, "历史系"));
            departs.Add(new Department(13, 4, "中文系"));
            return departs;
        }
        // 创建层级结构的根节点
        public void CreateTreeView(TreeView treeView)
        {
            foreach (var d in DepartmentCollection)
            {
                if (d.ParentID == 0)
                {
                    TreeViewItem rootItem = new TreeViewItem();
                    rootItem.Header = d.Name;
                    rootItem.Tag = d;
                    treeView.Items.Add(rootItem);
                    CreateTreeViewItem(rootItem,d);
                }
            }
        }
        // 创建层级结构的子节点 
        private void CreateTreeViewItem(TreeViewItem childItem,Department parent)
        {
            foreach (var d in DepartmentCollection)
            {
                if (d.ParentID == parent.ID)
                {
                    TreeViewItem child = new TreeViewItem();
                    child.Header = d.Name;
                    child.Tag = d;
                    childItem.Items.Add(child);
                    CreateTreeViewItem(child, d);
                }
            }
        }
    }
3、前台页面
<Grid>
        <TreeView Name="treeView" Width="200" AllowDrop="True">
            <TreeView.ContextMenu>
                <ContextMenu Name="tvMenu" Width="120" HorizontalAlignment="Left" VerticalAlignment="Top">
                    <MenuItem Header="添加" Name="miAdd"/>                               
                    <MenuItem Header="删除" Name="miDel"/>
                </ContextMenu>
            </TreeView.ContextMenu>
        </TreeView>
    </Grid> 
4、后台实现拖拽方法
首先需要把部门层级加载出来,只需调用CommanClass类的CreateTreeView方法即可
实现拖拽需要用到DragOver、Drop和MouseMove事件
            treeView.MouseMove += new MouseEventHandler(treeView_MouseMove);
            treeView.DragOver += new DragEventHandler(treeView_DragOver);
            treeView.Drop += new DragEventHandler(treeView_Drop); 
三个公共变量
        private Point _LastMouseDown;//鼠标按下的位置
        private TreeViewItem draggedItem, _target; //鼠标拖动项和存放的目标项

        //实现treeView.DragOver 事件
         void treeView_DragOver(object sender, DragEventArgs e)
        {
            try
            {
                Point currentPosition = e.GetPosition(treeView);
                if ((Math.Abs(currentPosition.X - _LastMouseDown.X) > 10.0) || (Math.Abs(currentPosition.Y - _LastMouseDown.Y) > 10.0))
                {
                    TreeViewItem item = GetNearestContainer(e.OriginalSource as UIElement);
                    e.Effects = CheckDropTarget(draggedItem, item) ? DragDropEffects.Move : DragDropEffects.None;
                }
                e.Handled = true;
            }
            catch { }
        }
        //获取TreeViewItem    
        private TreeViewItem GetNearestContainer(UIElement element)
        {
            TreeViewItem container = element as TreeViewItem;
            while ((container == null) && (element != null))
            {
                element = VisualTreeHelper.GetParent(element) as UIElement;
                container = element as TreeViewItem;
            }
            return container;
        }
        // 判断源项和目标项是否是自己本身    
        private bool CheckDropTarget(TreeViewItem sourceItem, TreeViewItem targetItem)
        {
            bool isEqual = false;
            if (sourceItem != null && targetItem != null)
            {
                if (!sourceItem.Header.ToString().Equals(targetItem.Header.ToString()))
                {
                    isEqual = true;
                }
            }
            return isEqual;
        }

        实现treeView.Drop 事件
        void treeView_Drop(object sender, DragEventArgs e)
        {
            try
            {
                e.Effects = DragDropEffects.None;
                e.Handled = true;
                TreeViewItem targetItem = GetNearestContainer(e.OriginalSource as UIElement);
                if (targetItem != null && draggedItem != null)
                {
                    _target = targetItem;
                    e.Effects = DragDropEffects.Move;
                }
            }
            catch { }
        }    
        //实现 treeView.MouseMove 事件    
        void treeView_MouseMove(object sender, MouseEventArgs e)
        {
            try
            {
                if (e.LeftButton == MouseButtonState.Pressed)
                {
                    Point currentPoint = e.GetPosition(treeView);
                    if ((Math.Abs(currentPoint.X - _LastMouseDown.X) > 10.0) || (Math.Abs(currentPoint.Y - _LastMouseDown.Y) > 10.0))
                    {
                        draggedItem = (TreeViewItem)treeView.SelectedItem;
                        if (draggedItem != null)
                        {
                            DragDropEffects finalDropEffect = DragDrop.DoDragDrop(treeView, treeView.SelectedValue, DragDropEffects.Move);
                            if ((finalDropEffect == DragDropEffects.Move) && _target != null)
                            {
                                if (!draggedItem.Header.ToString().Equals(_target.Header.ToString()))
                                {
                                    CopyItem(draggedItem, _target);
                                    _target = null;
                                    draggedItem = null;
                                }
                            }
                        }
                    }
                }
            }
            catch
            { }
        } 

        private void CopyItem(TreeViewItem sourceItem, TreeViewItem targetItem)
        {
            if (MessageBox.Show("是否将<" + sourceItem.Header.ToString() + ">移动到<" + targetItem.Header.ToString() + ">之下?", "询问",MessageBoxButton.YesNo , MessageBoxImage.Question) == MessageBoxResult.Yes)
            {
                AddChildFromDropItem(sourceItem, targetItem);
 
                TreeViewItem parentItem = FindVisualParent<TreeViewItem>(sourceItem);
                 //在源项的父项中移除源项
                if (parentItem == null)
                    treeView.Items.Remove(sourceItem);
                else
                    parentItem.Items.Remove(sourceItem);
            }
        } 
        //把源项及其子项移动到目标项    
        private void AddChildFromDropItem(TreeViewItem sourceItem, TreeViewItem targetItem)
        {
            if (sourceItem != null && targetItem != null)
            {
                TreeViewItem addItem = new TreeViewItem();
                addItem.Header = sourceItem.Header;
                addItem.Tag = sourceItem.Tag;
                Department source = addItem.Tag as Department;
                Department target = targetItem.Tag as Department;
                if (source != null && target != null)
                {
                    source.ParentID = target.ID;
                }
                targetItem.Items.Add(addItem);
                foreach (TreeViewItem item in sourceItem.Items)
                {
                    AddChildFromDropItem(item, addItem);
                }
            }
        } 
       //找到需要拖拽项的父项            
        private T FindVisualParent<T>(UIElement child) where T : UIElement
        {
            if (child == null)
                return null;
            UIElement parent = VisualTreeHelper.GetParent(child) as UIElement;
            while (parent != null)
            {
                T found = parent as T;
                if (found != null)
                    return found;
                else
                    parent = VisualTreeHelper.GetParent(parent) as UIElement;
            }
            return null;
        } 
最后实现右键菜单只需要在Loaded事件中加载MenuItem的Click事件就行 
例如删除右键
        miDel.Click += new RoutedEventHandler(miDel_Click);
        void miDel_Click(object sender, RoutedEventArgs e)
        {
            //throw new NotImplementedException();
        } 
最后实现效果
图片图片

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多