TreeView边学边总结

这是我第一次写博客。先介绍下情况吧,我现在是大三,专业是计算机,在一家公司实习,因为大学里三年都是混过来的,基本同龄的都知道,所以专业没学好,很差。但是现在又要面临实习,毕业找工作,幸好有认识的在一家公司上班,可以让我进去实习,语言c#。而我大学大一学c++,大二java,大三Android,c#是选修的,我没有学过。其他语言又很烂,水平跟大一进来一样,三年基本没编程过,计算机专业的应该知道这类人是什么情况,实验什么的都是靠班里学习好的人分享。说实话我很幸运,能有这样一个实习机会。可以说我是从头开始学c#。跟很多初次接触编程人一样,很迷惑,很苦恼,也有点后悔。废话不说了,开始总结下这几天学到的TreeView。

刚入门c#,所以比较基础,老鸟不要嘲笑新手。

TreeView有2种方法,一种是直接在代码里添加Node,这种方法我没有具体了解过,只是看了下,大概知道是一种硬编码。我学习的是另外一种,数据绑定的方法。

我写贴上自己写的代码,然后对代码进行解释。

MainWindow.xaml文件

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:local="clr-namespace:WpfApplication1">
    <Window.Resources>
        <ContextMenu x:Key="ss">                
        </ContextMenu>
    </Window.Resources>
    <Grid>
        <TreeView  SelectedItemChanged="treeview_SelectedItemChanged_1" Name="treeview" HorizontalAlignment="Left" Height="154" Margin="24,32,0,0" VerticalAlignment="Top" Width="112">
            <TreeView.ContextMenu>
                <ContextMenu>
                    <MenuItem Name="menuExpand" Header="全部展开" Click="menuExpand_Click_1"/>
                    <MenuItem Name="menuUnExpand" Header="全部折叠" Click="menuUnExpand_Click_1" />                   
                    <MenuItem Name="menuSelect" Header="全部选中" Click="menuSelect_Click_1"/>
                    <MenuItem Name="menuCancel" Header="全部取消" Click="menuCancel_Click_1"/>
                    <MenuItem Name="adeMenuNode" Header="增加节点" Click="addMenuNode_Click_1"/>
                    <MenuItem Name="DeleteNode" Header="删除节点" Click="DeleteNode_Click_2"/>
                </ContextMenu>
            </TreeView.ContextMenu>
            <TreeView.ItemContainerStyle>
                <Style TargetType="TreeViewItem">
                    <Setter Property="IsExpanded" Value="{Binding isExpand, Mode=TwoWay}"/>
                    <EventSetter Event="TreeViewItem.PreviewMouseRightButtonDown" Handler="TreeViewItem_PreviewMouseRightButtonDown"/>            
                </Style>
            </TreeView.ItemContainerStyle>

            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate DataType="{x:Type local:PropertyNodeItem}" ItemsSource="{Binding Path=Children}">
                    <StackPanel Name="stackPanel" Orientation="Horizontal">
                        <Image VerticalAlignment="Center" Source="{Binding ICON}"/>
                        <CheckBox ToolTip="{Binding ToolTip}" IsChecked="{Binding isChecked, Mode=TwoWay}" Tag="{Binding}" Checked="CheckBox_Checked_1"/>
                        <TextBlock VerticalAlignment="Center"  Text="{Binding DisplayName}"/>
                        <Image VerticalAlignment="Center" Source="{Binding EditIcon}"/>
                        
                        <StackPanel.ToolTip>
                            <TextBlock VerticalAlignment="Center" Text="{Binding Name}"/>
                        </StackPanel.ToolTip>
                    </StackPanel>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
            
        </TreeView>
        <Button Content="展开下一级" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="10,262,0,0" Click="Button_Click_1"/>
        <Button Content="全部展开" HorizontalAlignment="Left" Margin="131,262,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_2" RenderTransformOrigin="0.5,0.5"/>                                                             
        <Button Content="全部折叠" HorizontalAlignment="Left" Margin="260,262,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_3"/>
        <Label Content="加入节点名称" HorizontalAlignment="Left" Margin="24,211,0,0" VerticalAlignment="Top" Width="90"/>
        <TextBox HorizontalAlignment="Left" Height="23" Margin="108,214,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120" RenderTransformOrigin="0.146,0.533"/>

    </Grid>
</Window>

  <Window.Resources>
        <ContextMenu x:Key="ss">                
        </ContextMenu>
    </Window.Resources>

这部分不用理会,只是windows的资源引用,以后wpf样式,右键菜单选项什么的都可以放到这里。

 

<TreeView
 <TreeView  SelectedItemChanged="treeview_SelectedItemChanged_1" Name="treeview" HorizontalAlignment="Left" Height="154" Margin="24,32,0,0" VerticalAlignment="Top" Width="112">
            <TreeView.ContextMenu>
                <ContextMenu>
                    <MenuItem Name="menuExpand" Header="全部展开" Click="menuExpand_Click_1"/>
                    <MenuItem Name="menuUnExpand" Header="全部折叠" Click="menuUnExpand_Click_1" />                   
                    <MenuItem Name="menuSelect" Header="全部选中" Click="menuSelect_Click_1"/>
                    <MenuItem Name="menuCancel" Header="全部取消" Click="menuCancel_Click_1"/>
                    <MenuItem Name="adeMenuNode" Header="增加节点" Click="addMenuNode_Click_1"/>
                    <MenuItem Name="DeleteNode" Header="删除节点" Click="DeleteNode_Click_2"/>
                </ContextMenu>
            </TreeView.ContextMenu>

第一行设置了个SelectedItemChanged="treeview_SelectedItemChanged_1"  一个事件,后台代码没有写过,要写的可以自己增加,其他属性应该看的懂。

 <TreeView.ContextMenu>l里面的很多菜单项是我后台代码对树进行的一些操作。

 

 

 <TreeView.ItemContainerStyle>
                <Style TargetType="TreeViewItem">
                    <Setter Property="IsExpanded" Value="{Binding isExpand, Mode=TwoWay}"/>
                    <EventSetter Event="TreeViewItem.PreviewMouseRightButtonDown" Handler="TreeViewItem_PreviewMouseRightButtonDown"/>            
                </Style>
            </TreeView.ItemContainerStyle>

这段代码是为TreeView设置了个ItemContainerStyle,里面的IsExpand属性跟后台的isExpand进行了绑定,Mode是TwoWay方式,下面的事件是鼠标右击事件,不用管。


            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate DataType="{x:Type local:PropertyNodeItem}" ItemsSource="{Binding Path=Children}">
                    <StackPanel Name="stackPanel" Orientation="Horizontal">
                        <Image VerticalAlignment="Center" Source="{Binding ICON}"/>
                        <CheckBox ToolTip="{Binding ToolTip}" IsChecked="{Binding isChecked, Mode=TwoWay}" Tag="{Binding}" Checked="CheckBox_Checked_1"/>
                        <TextBlock VerticalAlignment="Center"  Text="{Binding DisplayName}"/>
                        
                        
                        <StackPanel.ToolTip>
                            <TextBlock VerticalAlignment="Center" Text="{Binding Name}"/>
                        </StackPanel.ToolTip>
                    </StackPanel>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
这是关键代码,DataType后面跟的是后台你定义的和TreeView绑定的类 类名字叫PropertyNodeItem Children是PropertyNodeItem的一个属性,但他是public List<PropertyNodeItem> Children { get; set; }
也就是你定义类型的一个List,当作数据源绑定给树。
在树里你可以给树设置Image,checkbox,textblock,然后跟你定义的PropertyNodeItem里的对应属性进行绑定,ToolTip是在鼠标移到textblock上会显示text绑定的name属性值。
下面是PropertyNodeItem的定义
public class PropertyNodeItem
    {
        //private bool _isExpand;
        public string ICON { get; set; }
        public string EditIcon { get; set; }
        public string DisplayName { get; set; }
        public string Name { get; set; }
        public bool isChecked { get; set; }
        public bool isExpand { get; set; }
       
        public List<PropertyNodeItem> Children { get; set; }
        public PropertyNodeItem()
        {
            Children = new List<PropertyNodeItem>();
        }       
    }
我在贴出后台代码
MainWindow.xamls.cs文件
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
   
    public partial class MainWindow : Window
    {        
        int NodeOfSLayer;
        public  List<PropertyNodeItem> ItemList = new List<PropertyNodeItem>();
        int i = 1;
        public MainWindow()
        {
            
            InitializeComponent();
            ShowTreeView();
           
        }    
        
        private void ShowTreeView()
        {
            
            PropertyNodeItem node1 = new PropertyNodeItem()
            {
                
                DisplayName="根节点",
                Name="yzf1",
                isExpand = false,
                
                
            };
            PropertyNodeItem node1child1 = new PropertyNodeItem()
            {
                DisplayName="子节点1",
                Name="yzf2",
                isExpand=false,
               // ICON =" Chrysanthemum.jpg"
            };
            PropertyNodeItem node1child1child1 = new PropertyNodeItem()
            {
                DisplayName = "子节点1_1",
                Name = "yzf7",
                isExpand = false,
                // ICON =" Chrysanthemum.jpg"
            };
            PropertyNodeItem node1child2 = new PropertyNodeItem()
            {
                DisplayName = "子节点2",
                Name = "yzf3",
                isExpand = false,
                // ICON =" Chrysanthemum.jpg"
            };
            node1child1.Children.Add(node1child1child1);
            node1.Children.Add(node1child1);
            node1.Children.Add(node1child2);
            NodeOfSLayer += 2;
            PropertyNodeItem node2 = new PropertyNodeItem()
            {
                DisplayName = "根节点",
                Name = "yzf4",
                isExpand = false,

            };
            PropertyNodeItem node2child1 = new PropertyNodeItem()
            {
                DisplayName = "子节点1",
                Name = "yzf5",
                isExpand = false,
                // ICON =" Chrysanthemum.jpg"
            };
            PropertyNodeItem node2child2 = new PropertyNodeItem()
            {
                DisplayName = "子节点2",
                Name = "yzf6",
                isExpand = false,
                // ICON =" Chrysanthemum.jpg"
            };
            node2.Children.Add(node2child1);
            node2.Children.Add(node2child2);
            ItemList.Add(node1);
            ItemList.Add(node2);
            NodeOfSLayer += 1;
            this.treeview.ItemsSource = ItemList;
        }
        private void AddChildNode()
        {
         // TreeViewItem
        }
        private void AddParentNode()
        {
 
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {

        }

        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
           
        }

        private void Button_Click_3(object sender, RoutedEventArgs e)
        {

        }

     
   
       
       
        private void menuExpand_Click_1(object sender, RoutedEventArgs e)
        {
            List<PropertyNodeItem> list =ItemList;
           if(e.Source!=null&&treeview.SelectedItem!=null)
           {

                SetNodeExpanded(list,true);
                //list.Add(tree);
           }
            ItemList = list;
            treeview.ItemsSource = null;
            treeview.ItemsSource = ItemList;         
        }

        private void menuUnExpand_Click_1(object sender, RoutedEventArgs e)
        {
            List<PropertyNodeItem> list = ItemList;
            if (e.Source != null && treeview.SelectedItem != null)
            {

                SetNodeExpanded(list, false);
                //list.Add(tree);
            }
            ItemList = list;
            treeview.ItemsSource = null;
            treeview.ItemsSource = ItemList;  
        }

        private void menuSelect_Click_1(object sender, RoutedEventArgs e)
        {
            List<PropertyNodeItem> list = ItemList;
            if(e.Source!=null)
            {
                
                if(list!=null&&list.Count>0)
                {
                    SetNodeChecked(list,true);
                }
            }
            ItemList = list;
            treeview.ItemsSource = null;
            treeview.ItemsSource = ItemList;
        }

        private void menuCancel_Click_1(object sender, RoutedEventArgs e)
        {
            List<PropertyNodeItem> list = ItemList;
            if (e.Source != null)
            {

                if (list != null && list.Count > 0)
                {
                    SetNodeChecked(list, false);
                }
            }
            ItemList = list;
            treeview.ItemsSource = null;
            treeview.ItemsSource = ItemList;
        }

        private void TreeViewItem_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
             
            TreeViewItem item = VisualUpwardSearch<TreeViewItem>(e.OriginalSource as DependencyObject) as TreeViewItem;
            if (item != null)
            {
                item.Focus();
                e.Handled = true;
            }
        }
        static DependencyObject VisualUpwardSearch<T>(DependencyObject source)
        {
            while (source != null && source.GetType() != typeof(T))
                source = VisualTreeHelper.GetParent(source);

            return source;
        }

        //private void menuExpandNode_Click_1(object sender, RoutedEventArgs e)
        //{
        //    PropertyNodeItem selected_item = treeview.SelectedItem as PropertyNodeItem;
        //    List<PropertyNodeItem> list = new List<PropertyNodeItem>();
        //   // PropertyNodeItem modelTag = (PropertyNodeItem)(((CheckBox)e.Source).Tag);
        //    list = ItemList;
        //    if (selected_item != null)
        //    {
        //        // PropertyNodeItem item = GetTree(list, selected_item.DisplayName);完全用不到GetTree函数,他返回的就是selected_item
        //        SetCrruntNodeExpanded(list, true);
        //    }
        //    else
        //    {
        //        MessageBox.Show("请选择一个节点");
        //    }
        //    ItemList = list;
        //    treeview.ItemsSource = null;
        //    treeview.ItemsSource = ItemList;
        //}

        private void treeview_SelectedItemChanged_1(object sender, RoutedPropertyChangedEventArgs<object> e)
        {      
        }

        private void addMenuNode_Click_1(object sender, RoutedEventArgs e)
        {
            PropertyNodeItem selected_item = treeview.SelectedItem as PropertyNodeItem;
            
            List<PropertyNodeItem> list = new List<PropertyNodeItem>();
            list=ItemList;
            PropertyNodeItem node1 = new PropertyNodeItem()
            {
                DisplayName = "增加的节点",
                Name = "addNode",
                isExpand = false,
            };
            if(selected_item!=null&&list!=null)
            {
            AddChildrenNode(list, node1,selected_item); 
            }
            ItemList = list;
            treeview.ItemsSource = null;
            treeview.ItemsSource = ItemList;
            
        }
        private void AddChildrenNode(List<PropertyNodeItem> list,PropertyNodeItem node,PropertyNodeItem selected_item)
        {
            foreach (PropertyNodeItem item in list)
            {
                if (item == selected_item)
                {
                    item.Children.Add(node);
                }
                if(item.Children!=null)
                {
                    AddChildrenNode(item.Children, node, selected_item);
                }
            }
        }
        private PropertyNodeItem SearchNode( List< PropertyNodeItem> ParentList, PropertyNodeItem SelectItem)
        {
            if (ParentList != null && ParentList.Count > 0)
            {
                foreach (PropertyNodeItem parentModel in ParentList)
                {
                    if (parentModel.Children != null && parentModel.Children.Count > 0)
                    {
                        SearchNode(parentModel.Children, SelectItem);
                    }
                    if (parentModel == SelectItem)
                    {
                        return parentModel;
                    }

                }
            }
            return null;            
        }
        private void SetNodeExpanded(List<PropertyNodeItem> itemlist,bool expand)
        {
            if (itemlist != null && itemlist.Count > 0)
                    {
                        foreach (PropertyNodeItem item in itemlist)
                        {
                            item.isExpand = expand;
                            if(item.Children!=null&&item.Children.Count>0)
                            {
                                SetNodeExpanded(item.Children,expand);
                            }
                        }
                    }
        }
        private void SetNodeChecked(List<PropertyNodeItem> itemlist, bool check)
        {
            if (itemlist != null && itemlist.Count > 0)
            {
                foreach (PropertyNodeItem item in itemlist)
                {
                    item.isChecked = check;
                    if (item.Children != null && item.Children.Count > 0)
                    {
                        SetNodeChecked(item.Children, check);
                    }
                }
            }
        }
        //private void SetCrruntNodeExpanded(List<PropertyNodeItem> itemlist,bool expand)
        //{
        //        if(itemlist!=null&&itemlist.Count>0)
        //        {
        //            foreach(PropertyNodeItem item in itemlist)
        //           {
                    
        //                if (i == 0)
        //                {
        //                    i = 1;
        //                    return;
        //                }
        //                else
        //                {
        //                    item.isExpand = expand;
        //                    if(item.Children!=null&&item.Children.Count>0)
        //                    {
        //                        i = i - 1;
        //                        SetCrruntNodeExpanded(item.Children,expand);
        //                    }
        //                }
                    
        //           }
        //        }
 
        //}
        private PropertyNodeItem GetTree(List<PropertyNodeItem> list,string displayname)
        {
            if (list != null && list.Count > 0)
            {
                for(int i=0;i<list.Count;i++)
              {
                if(list[i].DisplayName==displayname)
                {
                    return list[i];
                }
                    if(list[i].Children!=null&&list[i].Children.Count>0)
                    {
                       PropertyNodeItem returnNodeItem=GetTree(list[i].Children,displayname);
                        if(returnNodeItem!=null)
                        {
                            return returnNodeItem;
                        }
                    }
              }
            }
            return null;
        }
        private void DeleteNode_Click_2(object sender, RoutedEventArgs e)
        {
            //在下面的RemoveNode函数里 要注意的是方法里遍历treeview的时候要用for循环,而不能用foreach,
            //因为foreach是只读操作,不允许删除,更新、添加没有问题,所以在上面的AddChildrenNode函数里确可以用foreach。
            PropertyNodeItem selected_item = treeview.SelectedItem as PropertyNodeItem;
            List<PropertyNodeItem> list = new List<PropertyNodeItem>();
            list = ItemList;
            if (selected_item.DisplayName == "根节点")
            {
                MessageBox.Show("根节点不允许删除");
            }
            else
            {
                if (selected_item != null)
                {
                    RemoveNode(list, selected_item);
                }
                ItemList = list;
                treeview.ItemsSource = null;
                treeview.ItemsSource = ItemList;
            }
        }
        private void RemoveNode(List<PropertyNodeItem> list,PropertyNodeItem selectItem)
        {
            for (int i = 0; i < list.Count;i++)
            {
                if (list[i] == selectItem)
                {
                    list.Remove(list[i]);
                    return;
                }
                if (list[i].Children != null)
                {
                    RemoveNode(list[i].Children, selectItem);
                }
            }
 
        }
        private void CheckBox_Checked_1(object sender, RoutedEventArgs e)
        {
           // PropertyNodeItem modelTag = (PropertyNodeItem)(((CheckBox)e.Source).Tag);
        }

    
     
    
    }
    public class PropertyNodeItem
    {
        private bool _isExpand;
        public string ICON { get; set; }
        public string EditIcon { get; set; }
        public string DisplayName { get; set; }
        public string Name { get; set; }
        public bool isChecked { get; set; }
        public bool isExpand { get; set; }
       
        public List<PropertyNodeItem> Children { get; set; }
        public PropertyNodeItem()
        {
            Children = new List<PropertyNodeItem>();
        }


       
    }
}

里面具体的一些菜单事件的函数先可以不用看。

private void ShowTreeView()和定义的类PropertyNodeItem就可以呈现一个简单的树了,Image属性我没有给他赋值,大家可以自己赋值。在项目里引用一些图片,然后我上面注释的代码
// ICON =" Chrysanthemum.jpg"

这句话就是用来设置图片的
运行后样子是这样的


这些菜单的事件下次再讲。菜单事件是可以运行起来的,有兴趣的可以自己跑起来看看。






posted @ 2013-08-28 22:30  YzfMuma  阅读(509)  评论(1编辑  收藏  举报