(转) WPF Treeview 学习 图标,checkbox,右键菜单

http://blog.csdn.net/alsmile/article/details/6606673

刚开始接触的这个控件,有点不知道怎么用。网上看了下,好像大家都觉得不如winform里面的好使。反正,我以前是用mfc做界面的,对c#不熟。网上看了几个例子,自己动手做了一下,现在把大概步骤记录下来。我这里比较简单,没有用什么模式。网上有一篇《使用ViewModel模式来简化WPF的TreeView》大家可以看看。

一、一个简单的树

首先、定义一个树节点的类,用来保存树节点信息:

TreeItem.cs文件:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;

namespace WPFTreeviewExamples
{
   class TreeItem
   {
       // 构造函数
       public TreeItem()
       {
            children= new ObservableCollection<TreeItem>();
       }

       //////////////////////////////////////////////////////////////////////////
       // 节点文字信息
       public stringtext
       {
           get;
           set;
       }

       // 节点其他信息
       // ...

       // 父节点
       public TreeItemparent
       {
            get;
            set;
       }
       // 子节点
       public ObservableCollection<TreeItem> children

       {
            get;
            set;
       }

       //////////////////////////////////////////////////////////////////////////
   }

}

然后、在xaml文件中定义树的属性样式:

<TreeView Name="treeViewSimple" >
   <TreeView.ItemContainerStyle>
      <Style TargetType="{x:TypeTreeViewItem}">
         <Setter Property="IsExpanded" Value="true"/>
      </Style>
   </TreeView.ItemContainerStyle>
   <TreeView.Resources>
      <HierarchicalDataTemplate DataType="{x:Type local:TreeItem}"  ItemsSource="{Binding Path=children}">
         <StackPanel Orientation="Horizontal" Margin="0,2,0,2">                      
            <TextBlock Text="{Binding text}" ToolTip="{Binding text}"/>
         </StackPanel>
      </HierarchicalDataTemplate>               
   </TreeView.Resources>
</TreeView>

其中:<Setter Property="IsExpanded" Value="true"/>表示所有节点都展开。

HierarchicalDataTemplate定义节点样式。DataType="{x:Typelocal:TreeItem}用来表明存储节点数据的类是什么。

二、带图标的树

很简单,只要添加图标相关信息即可:

TreeItem.cs文件:

//////////////////////////////////////////////////////////////////////////
       // 节点文字信息
       public stringtext
       {
            get;
            set;
       }

       // 节点图标路径
       public stringitemIcon
       {
            get;
            set;
       }

       // 节点其他信息
       // ...

xaml文件

<TreeView.Resources>
   <HierarchicalDataTemplate DataType="{x:Type local:TreeItem}"  ItemsSource="{Binding Path=children}">
      <StackPanel Orientation="Horizontal" Margin="0,2,0,2"> 
         <Image VerticalAlignment="Center" Source="{Binding itemIcon}" ></Image>
            <TextBlock VerticalAlignment="Center" Text="{Binding text}" ToolTip="{Binding text}"/>
      </StackPanel>
   </HierarchicalDataTemplate>               
</TreeView.Resources>

三、更多功能的树

1、  首先,让我加一个checkbox

这需要完善 TreeItem:

让它继承与INotifyPropertyChanged 接口,以便通知checkbox状态改变:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace WPFTreeviewExamples
{
   class TreeItem: INotifyPropertyChanged
   {
       // 构造函数
       public TreeItem()
       {
            children= new ObservableCollection<TreeItem>();
       }

       //////////////////////////////////////////////////////////////////////////
       // 节点文字信息
       public stringtext
       {
            get;
            set;
       }
       // 节点图标路径
       public stringitemIcon
       {
            get;
            set;
       }

       // 节点其他信息
       // ...
       // 父节点

       public TreeItemparent
       {
            get;
            set;
       }
       // 子节点
       public ObservableCollection<TreeItem> children
       {
            get;
            set;
       }
       //////////////////////////////////////////////////////////////////////////
       ////////   Check 相关信息  ///////////////////////////////////////////
       bool? _isChecked= false;
       public bool?IsChecked
       {
            get{ return _isChecked;}
            set{ this.SetIsChecked(value, true, true); }
       }

       void SetIsChecked(bool? value, bool updateChildren,bool updateParent)
       {
            if(value == _isChecked)
                return;
            _isChecked= value;
            if(updateChildren && _isChecked.HasValue)
            {
                foreach(TreeItem childin children)
                {
                    child.SetIsChecked(_isChecked,true, false);
                }
            }
            if(updateParent && parent != null)
            {
                parent.VerifyCheckState();
            }
            this.OnPropertyChanged("IsChecked");
       }

       void VerifyCheckState()
       {
            bool?state = null;
            for(int i = 0; i < this.children.Count;++i)
            {
                bool? current = this.children[i].IsChecked;
                if(i == 0)
                {
                    state= current;
                }
                elseif (state !=current)
                {
                    state= null;
                    break;
                }
            }
            this.SetIsChecked(state,false, true);
       }

       ////////////////////////////////////////////////////////////////////////////
       void OnPropertyChanged(string prop)
       {
            if(this.PropertyChanged!= null)
                this.PropertyChanged(this,new PropertyChangedEventArgs(prop));
       }
       public eventPropertyChangedEventHandler PropertyChanged;
       //////////////////////////////////////////////////////////////////////////
   }
}
<TreeView.Resources>
   <HierarchicalDataTemplate DataType="{x:Type local:TreeItem}"  ItemsSource="{Binding Path=children}">
      <StackPanel Orientation="Horizontal" Margin="0,2,0,2"> 
         <CheckBox Focusable="False" IsChecked="{Binding IsChecked,Mode=TwoWay}"VerticalAlignment="Center" />
         <Image VerticalAlignment="Center" Source="{Binding itemIcon}" ></Image>
         <TextBlock VerticalAlignment="Center" Text="{Binding text}" ToolTip="{Binding text}"/>
      </StackPanel>
   </HierarchicalDataTemplate>               
</TreeView.Resources>
void InitTree()
       {
            tree= new TreeItem();
            // 添加一级顶层子节点
            TreeItemroot = new TreeItem();
            root.text = "根节点";
            root.itemIcon = "./image/root.png";
            // 把根节点加进来
            tree.children.Add(root);
            root.parent = tree;
            // 给根节点加一些子节点
            TreeItemhubei = new TreeItem();
            hubei.text = "湖北";
            hubei.itemIcon = "./image/Provine.png";
            root.children.Add(hubei);
            hubei.parent = root;
            // 给湖北下加几个城市
            TreeItemwuhan = new TreeItem();
            wuhan.text = "武汉";
            wuhan.itemIcon = "./image/City.png";
            TreeItemxiaogan = newTreeItem();
            xiaogan.text = "孝感";
            xiaogan.itemIcon = "./image/City.png";
            TreeItemxiangyang = newTreeItem();
            xiangyang.text = "襄阳";
            xiangyang.itemIcon = "./image/City.png";
            hubei.children.Add(wuhan);
            wuhan.parent = hubei;
            hubei.children.Add(xiaogan);
            xiaogan.parent = hubei;
            hubei.children.Add(xiangyang);
            xiangyang.parent = hubei;
            // 给根节点加一些子节点
            TreeItemfamily = newTreeItem();
            family.text = "我的家";
            family.itemIcon = "./image/Provine.png";
            root.children.Add(family);
            family.parent = root;
            // 给湖北下加几个城市
            TreeItemdad = new TreeItem();
            dad.text = "爸爸";
            dad.itemIcon = "./image/City.png";
            TreeItemmom = new TreeItem();
            mom.text = "妈妈";
            mom.itemIcon = "./image/City.png";
            TreeItemme = new TreeItem();
            me.text = "";
            me.itemIcon = "./image/City.png";
            TreeItembrother = newTreeItem();
            brother.text = "弟弟";
            brother.itemIcon = "./image/City.png";
            family.children.Add(dad);
            dad.parent = family;
            family.children.Add(mom);
            mom.parent = family;
            family.children.Add(me);
            me.parent = family;
            family.children.Add(brother);
            brother.parent = family;
            // 把数据绑定到控件
            treeViewMine.ItemsSource = tree.children;
        }

2、  tree的节点选择

在当前选择项(非checkbox)下加一个节点:

TreeItem selectItem = treeViewMine.SelectedItem as TreeItem;
            if(selectItem != null)
            {
                TreeItemnewItem = newTreeItem();
                newItem.text = "这是一个新项";
                newItem.itemIcon = "./image/City.png";
                selectItem.children.Add(newItem);
                newItem.parent = selectItem;
            }

删除获得焦点的选择项:

TreeItem selectItem = treeViewMine.SelectedItem as TreeItem;
selectItem.parent.children.Remove(selectItem);

删除checkbox选择的项

private void button1_Click(object sender, RoutedEventArgs e)
       {
          TreeDelChecked(tree);
       }
       bool TreeDelChecked(TreeItem item)
       {
            begin:

            foreach(TreeItem itemChildin item.children)

            {

                // 如果删除一个子节点后,foreach要重新遍历

                if(TreeDelChecked(itemChild))

                {

                    gotobegin;

                }

            }

 

           if(item.IsChecked.HasValue) //check for avalue

            {

                if((bool)item.IsChecked && item.parent != null) //now this cast is safe

                {                   

                    item.parent.children.Remove(item);

 

                    returntrue;

                }

            }

 

            returnfalse;

       }

3、树右键选中和右键菜单

参考《在WPF的TreeView中实现右键选定》http://www.cnblogs.com/TianFang/archive/2010/02/10/1667153.html

<TreeView.ItemContainerStyle >

                <Style TargetType="{x:TypeTreeViewItem}" >

                    <Setter Property="IsExpanded" Value="true"/>

                    <EventSetter Event="TreeViewItem.PreviewMouseRightButtonDown" Handler="treeViewMine_PreviewMouseRightButtonDown"/>

                </Style>

            </TreeView.ItemContainerStyle>
private void treeViewMine_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)

       {

            TreeViewItemitem = VisualUpwardSearch<TreeViewItem>(e.OriginalSource as DependencyObject) asTreeViewItem;

            if(item != null)

            {

                item.ContextMenu = GetItemRightContextMenu();

 

                item.Focus();

                e.Handled = true; 

            }

       }

 

       static DependencyObjectVisualUpwardSearch<T>(DependencyObjectsource)

       {

            while(source != null&& source.GetType()!= typeof(T))

                source= VisualTreeHelper.GetParent(source);

 

            returnsource;

       }

 

       // 获得右键上下文菜单

       ContextMenu GetItemRightContextMenu()

       {

            ContextMenumenu = new ContextMenu();

            MenuItemmenuItem = newMenuItem();

            menuItem.Header = "菜单";

            menuItem.Click += new RoutedEventHandler(treeMenu_Click);

            menu.Items.Add(menuItem);

 

            returnmenu;

       }

 

       private voidtreeMenu_Click(objectsender, RoutedEventArgse)

       {

            if(MessageBox.Show("大家好,我是树的右键菜单事件!", "提示", MessageBoxButton.OKCancel,MessageBoxImage.Information)!= MessageBoxResult.OK)

            {

                return;

            }

  }
原文地址:https://www.cnblogs.com/xiefang2008/p/6587161.html