zoukankan      html  css  js  c++  java
  • (转) 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;
    
                }
    
      }
  • 相关阅读:
    九、linux-msyql下的mysql主从复制深度实战
    八、linux-mysql的mysql主从复制原理和实战
    七、linux-mysql下mysql增量备份与恢复
    六、linux-mysql的mysql字符集问题
    入坑django2
    python根据已有数据库生成model.py
    docker 常用命令记录
    gitlab自带的Nginx与原Nginx冲突的解决方案
    linux下PHP安装redis扩展
    jenkins自动部署代码到多台服务器
  • 原文地址:https://www.cnblogs.com/xiefang2008/p/6587161.html
Copyright © 2011-2022 走看看