顺便分享一下用WPF设计自定义tree控件树.一些增删改查节点的方式

 

背景

我觉得把自己的设计过程的小demo整理分享出来.顺便后续自己的回溯挺好

效果图

顺便分享一下用WPF设计自定义tree控件树.一些增删改查节点的方式

关键代码

节点设计类

namespace Tree
{
   public class ARenderable : ViewModelBase
   {
        private String _name;
        /// <summary>
        /// Name of the renderable object
        /// </summary>
        public String Name
        {
            get { return _name; }
            set
            {
                _name = value;
                RaisePropertyChanged("Name");
            }
        }

        private bool _render;
        /// <summary>
        /// If true, the object will be rendered
        /// </summary>
        public bool Render
        {
            get { return _render; }
            set
            {
                _render = value;
                RaisePropertyChanged("Render", !value, value, true);
            }
        }

        private bool _isSelected;
        /// <summary>
        /// Selected in the tree view
        /// </summary>
        public bool IsSelected
        {
            get
            {
                return _isSelected;
            }
            set
            {
                if (_isSelected != value)
                {
                    _isSelected = value;
                    RaisePropertyChanged("IsSelected");
                }
            }
        }


        private bool _isExpanded;
        /// <summary>
        /// Expanded in the tree view
        /// </summary>
        public bool IsExpanded
        {
            get
            {
                return _isExpanded;
            }
            set
            {
                if (_isExpanded != value)
                {
                    _isExpanded = value;
                    RaisePropertyChanged("IsExpanded");
                }
            }
        }

        private ARenderable _parent;
        public ARenderable(ARenderable parent)
        {
            _parent = parent;
            Children = new ObservableCollection<ARenderable>();
        }

        private ObservableCollection<ARenderable> _children;

        public void CreateChild()
        {
            if(_children==null)
            {
                _children = new ObservableCollection<ARenderable>();
            }
        }
        /// <summary>
        /// Children in the tree
        /// </summary>
        public ObservableCollection<ARenderable> Children
        {
            get { return _children; }
            private set { _children = value; }
        }

        public override string ToString()
        {
            return $"Name: {_name}  render: {_render}  selected: {_isSelected}  isExpanded: {_isExpanded}";
        }

    }
}

 

节点控制的关键代码

1.创建集合并初始化

 public ObservableCollection<ARenderable> RenderActors
        {
            get; set;
        }


 private void wndLoaded(object sender, RoutedEventArgs e)
        {
            RenderActors = new ObservableCollection<ARenderable>();
            //初始化....
            {
                for(int i=0;i<10;i++)
                {
                    ARenderable temp = new ARenderable(null);
                    temp.Name = $"name_{i}";
                    temp.Render = (i % 2 == 0) ?false : true;
                    temp.IsExpanded = (i%2==0) ?false : true;

                    if (i % 3 == 0)
                    {
                        for (int j = 0; j < 5; j++)
                        {
                            ARenderable chidt = new ARenderable(null);
                            chidt.Name = $"name_{i}->{j}";
                            chidt.Render = (j % 2 == 0) ? false : true;
                            chidt.IsExpanded = (j % 2 == 0) ? false : true;
                            temp.Children.Add(chidt);
                        }
                    }

                    RenderActors.Add(temp);
                }

            }

            _treeView.ItemsSource = RenderActors;

        }

2.对集合的操作

 这里对节点的任何操作,都是递归处理的.

 #region tree的属性操作.
        public void deleteItem(ref ObservableCollection<ARenderable> collectionList, ARenderable node)
        {
            if(collectionList!=null)
            {
                foreach (var item in collectionList)
                {
                    if(item.Name == node.Name)
                    {
                        collectionList.Remove(node);
                        break;
                    }

                    ObservableCollection<ARenderable> datalist = item.Children;
                    deleteItem(ref datalist,node);
                }
            }
            
        }
        public void AddItem(ref ObservableCollection<ARenderable> collectionList, ARenderable ParentNode,ARenderable childNode)
        {
            if (collectionList != null)
            {
                foreach (var item in collectionList)
                {
                    if (item.Name == ParentNode.Name)
                    {
                        if(item.Children == null)
                        {
                            item.CreateChild();
                        }
                        item.Children.Add(childNode);
                        break;
                    }

                    ObservableCollection<ARenderable> datalist = item.Children;
                    AddItem(ref datalist, ParentNode, childNode);
                }
            }

        }

        public void updadaItem(ref ObservableCollection<ARenderable> collectionList, ARenderable updataNode, ARenderable childNode)
        {
            if(collectionList!=null)
            {
                for (int i=0;i< collectionList.Count;i++)
                {
                    if(collectionList[i].Name == updataNode.Name)
                    {
                        collectionList[i].Name = childNode.Name;
                        collectionList[i].IsExpanded = childNode.IsExpanded;
                        break;
                    }

                    ObservableCollection<ARenderable> datalist = collectionList[i].Children;
                    updadaItem(ref datalist,updataNode,childNode);
                }
            }
        }


        #endregion

3.添加操作

  static int index = 0;
        private void MenuItem_Click_add(object sender, RoutedEventArgs e)
        {
            var ParentNode = _treeView.SelectedItem as ARenderable;
            if (ParentNode != null)
            {
                ARenderable tempChild = new ARenderable(ParentNode);
                tempChild.Name = "new node " + index.ToString();
                tempChild.IsExpanded = true;
                tempChild.IsExpanded = true;
                index++;
                ObservableCollection<ARenderable> datalist = RenderActors;
                AddItem(ref datalist, ParentNode, tempChild);
                ParentNode.IsExpanded = true;
            }
        }
 private void MenuItem_Click_box(object sender, RoutedEventArgs e)
        {
            var node = _treeView.SelectedItem as ARenderable;
            if (node != null)
            {
                //删除此项目
                if(node.Children!=null) MessageBox.Show($"{node.ToString()}    count:             {node.Children.Count}");
                else MessageBox.Show(node.ToString());
            }
        }

结束

以上就是操作控件树的整个关键代码.其实掌握递归的思想.很多复杂的计算以及控制,都可迎刃而解.但是这是一把双刃剑.一定要注意内存以及结束条件的约束

下次分享一个: 博彩行业.对任意给定的20组集合. 求取全排列以及 输出结果的整个算法设计流程(排列有坑,各位且珍惜)

上一篇:WPF 列表控件数据源绑定多个数据集合方法


下一篇:WPF listbox 实现动态滚轮下拉定位