WPF 帶CheckBox、圖標的TreeView
在WPF實際項目開發的時候,經常會用到帶CheckBox的TreeView,雖然微軟在WPF的TreeView中沒有提供該功能,但是微軟在WPF中提供強大的ItemTemplate模板功能和自定義樣式,那我們可以自己寫一個這樣的控件供自己使用。
?我自己寫的這個比較簡單。
首先寫一個供TreeView使用的數據模型,并且實現INotifyPropertyChanged接口,用于向客戶端(通常是執行綁定的客戶端)發出某一屬性值已更改的通知,當屬性改變時,相應的UI表現也改變。主要字段Id,Name,Icon,ToolTip,IsChecked,IsExpanded,Parent,Children
//*************************************************** // // 文件名(FileName) : TreeModel.cs // // 作者(Author) : zsm // // 創建時間(CreateAt): 2013-03-18 14:23:58 // // 描述(Description) : 供TreeView實用的數據模型 // //*************************************************** using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel;namespace Com.FMS.Model {public class TreeModel : INotifyPropertyChanged{#region 私有變量/// <summary>/// Id值/// </summary>private string _id;/// <summary>/// 顯示的名稱/// </summary>private string _name;/// <summary>/// 圖標路徑/// </summary>private string _icon;/// <summary>/// 選中狀態/// </summary>private bool _isChecked;/// <summary>/// 折疊狀態/// </summary>private bool _isExpanded;/// <summary>/// 子項/// </summary>private IList<TreeModel> _children;/// <summary>/// 父項/// </summary>private TreeModel _parent;#endregion /// <summary>/// 構造/// </summary>public TreeModel(){Children = new List<TreeModel>();_isChecked = false;IsExpanded = false;_icon = "/Images/16_16/folder_go.png";}/// <summary>/// 鍵值/// </summary>public string Id{get { return _id; }set { _id = value; }}/// <summary>/// 顯示的字符/// </summary>public string Name{get { return _name; }set { _name = value; }}/// <summary>/// 圖標/// </summary>public string Icon{get { return _icon; }set { _icon = value; }}/// <summary>/// 指針懸停時的顯示說明/// </summary>public string ToolTip {get {return String.Format("{0}-{1}", Id, Name);}}/// <summary>/// 是否選中/// </summary>public bool IsChecked{get{return _isChecked;}set{if (value != _isChecked){_isChecked = value;NotifyPropertyChanged("IsChecked");if (_isChecked){//如果選中則父項也應該選中if (Parent != null){Parent.IsChecked = true;}}else{//如果取消選中子項也應該取消選中foreach (TreeModel child in Children){child.IsChecked = false;}}}}}/// <summary>/// 是否展開/// </summary>public bool IsExpanded{get { return _isExpanded; }set{if (value != _isExpanded){//折疊狀態改變_isExpanded = value;NotifyPropertyChanged("IsExpanded");}}}/// <summary>/// 父項/// </summary>public TreeModel Parent{get { return _parent; }set { _parent = value; }}/// <summary>/// 子項/// </summary>public IList<TreeModel> Children{get { return _children; }set { _children = value; }}/// <summary>/// 設置所有子項的選中狀態/// </summary>/// <param name="isChecked"></param>public void SetChildrenChecked(bool isChecked){foreach (TreeModel child in Children){child.IsChecked = IsChecked;child.SetChildrenChecked(IsChecked);}}/// <summary>/// 設置所有子項展開狀態/// </summary>/// <param name="isExpanded"></param>public void SetChildrenExpanded(bool isExpanded) {foreach (TreeModel child in Children){child.IsExpanded = isExpanded;child.SetChildrenExpanded(isExpanded);}}/// <summary>/// 屬性改變事件/// </summary>public event PropertyChangedEventHandler PropertyChanged;private void NotifyPropertyChanged(String info){if (PropertyChanged != null){PropertyChanged(this, new PropertyChangedEventArgs(info));}}} }
創建一個用戶控件,主要含有一個TreeView控件,ContextMenu右鍵菜單項,UI代碼如下(其中的路徑請根據實際修改):
<UserControl x:Class="Com.FMS.View.UserControls.ZsmTreeView"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Com.FMS.Model"mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"><Grid><DockPanel><Border DockPanel.Dock="Bottom"><StackPanel Orientation="Horizontal" ToolTip="右鍵有更多功能哦!"><Image Height="16" Width="16" Source="Images/16_16/emoticon_smile.png"></Image><Label Content="右鍵有更多功能哦!" Foreground="Gray"></Label></StackPanel></Border><Border><TreeView Name="tvZsmTree"><TreeView.ContextMenu><ContextMenu><MenuItem Name="menuExpandAll" Header="全部展開" Click="menuExpandAll_Click"><MenuItem.Icon><Image Source="/Com.FMS;component/Images/16_16/folder_open_arrow.png" /></MenuItem.Icon></MenuItem><MenuItem Name="menuUnExpandAll" Header="全部折疊" Click="menuUnExpandAll_Click"><MenuItem.Icon><Image Source="/Com.FMS;component/Images/16_16/folder_close_arrow.png" /></MenuItem.Icon></MenuItem><MenuItem Name="menuSelectAll" Header="全部選中" Click="menuSelectAll_Click"><MenuItem.Icon><Image Source="/Com.FMS;component/Images/16_16/tick.png" /></MenuItem.Icon></MenuItem><MenuItem Name="menuUnSelectAll" Header="全部取消" Click="menuUnSelectAll_Click"><MenuItem.Icon><Image Source="/Com.FMS;component/Images/16_16/delete.png" /></MenuItem.Icon></MenuItem></ContextMenu></TreeView.ContextMenu><TreeView.ItemContainerStyle><Style TargetType="TreeViewItem"><Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"></Setter><EventSetter Event="TreeViewItem.PreviewMouseRightButtonDown" Handler="TreeViewItem_PreviewMouseRightButtonDown"/></Style></TreeView.ItemContainerStyle><TreeView.ItemTemplate><HierarchicalDataTemplate DataType="{x:Type local:TreeModel}" ItemsSource="{Binding Children}"><StackPanel Margin="-2,0,0,0" Orientation="Horizontal" x:Name="staTree"><CheckBox ToolTip="{Binding ToolTip}" FontSize="14" FontFamily="微軟雅黑" Tag="{Binding Children}" IsChecked="{Binding IsChecked, Mode=TwoWay}"><StackPanel Orientation="Horizontal"><Image VerticalAlignment="Center" Source="{Binding Icon}" ></Image><TextBlock Text="{Binding Name}"></TextBlock></StackPanel><CheckBox.ContextMenu><ContextMenu><MenuItem Name="menuSelectAllChild" Header="全部選中子項" Click="menuSelectAllChild_Click"><MenuItem.Icon><Image Source="/Com.FMS;component/Images/16_16/tick.png" /></MenuItem.Icon></MenuItem></ContextMenu></CheckBox.ContextMenu></CheckBox></StackPanel><HierarchicalDataTemplate.Triggers><DataTrigger Binding="{Binding IsChecked}" Value="true"><Setter TargetName="staTree" Property="Background" Value="White"/></DataTrigger></HierarchicalDataTemplate.Triggers></HierarchicalDataTemplate></TreeView.ItemTemplate></TreeView></Border></DockPanel></Grid> </UserControl>
交互邏輯的代碼中,現在主要有控件數據ItemsSourceData屬性,設置對應Id的項為選中狀態SetCheckedById、忽略層次關系的情況下獲取選中項CheckedItemsIgnoreRelation等方法,以及右鍵的選中所有子項菜單、全部選中、全部取消選中、全部折疊、全部展開等事件,交互邏輯代碼為:
//*************************************************** // // 文件名(FileName) : ZsmTreeView.xaml.cs // // 作者(Author) : zsm // // 創建時間(CreateAt): 2013-03-15 16:52:40 // // 描述(Description) : 帶CheckBox的TreeView控件的交互邏輯代碼 // //*************************************************** using System; using System.Collections.Generic; using System.Linq; using System.Text; 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 Com.FMS.View.UserControls {/// <summary>/// ZsmTreeView.xaml 的交互邏輯/// </summary>public partial class ZsmTreeView : UserControl{#region 私有變量屬性/// <summary>/// 控件數據/// </summary>private IList<Model.TreeModel> _itemsSourceData;#endregion/// <summary>/// 構造/// </summary>public ZsmTreeView(){InitializeComponent();}/// <summary>/// 控件數據/// </summary>public IList<Model.TreeModel> ItemsSourceData {get { return _itemsSourceData; }set{_itemsSourceData = value;tvZsmTree.ItemsSource = _itemsSourceData;}}/// <summary>/// 設置對應Id的項為選中狀態/// </summary>/// <param name="id"></param>/// <returns></returns>public int SetCheckedById(string id, IList<Model.TreeModel> treeList) {foreach (var tree in treeList){if (tree.Id.Equals(id)){tree.IsChecked = true;return 1;}if (SetCheckedById(id, tree.Children) == 1){return 1;}}return 0;}/// <summary>/// 設置對應Id的項為選中狀態/// </summary>/// <param name="id"></param>/// <returns></returns>public int SetCheckedById(string id){foreach (var tree in ItemsSourceData){if (tree.Id.Equals(id)){tree.IsChecked = true;return 1;}if (SetCheckedById(id, tree.Children) == 1){return 1;}}return 0;}/// <summary>/// 獲取選中項/// </summary>/// <returns></returns>public IList<Model.TreeModel> CheckedItemsIgnoreRelation(){return GetCheckedItemsIgnoreRelation(_itemsSourceData);}/// <summary>/// 私有方法,忽略層次關系的情況下,獲取選中項/// </summary>/// <param name="list"></param>/// <returns></returns>private IList<Model.TreeModel> GetCheckedItemsIgnoreRelation(IList<Model.TreeModel> list){IList<Model.TreeModel> treeList = new List<Model.TreeModel>();foreach (var tree in list){if (tree.IsChecked){treeList.Add(tree);}foreach (var child in GetCheckedItemsIgnoreRelation(tree.Children)){treeList.Add(child);}}return treeList;}/// <summary>/// 選中所有子項菜單事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void menuSelectAllChild_Click(object sender, RoutedEventArgs e){if (tvZsmTree.SelectedItem != null){Model.TreeModel tree = (Model.TreeModel)tvZsmTree.SelectedItem;tree.IsChecked = true;tree.SetChildrenChecked(true);}}/// <summary>/// 全部展開菜單事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void menuExpandAll_Click(object sender, RoutedEventArgs e){foreach (Model.TreeModel tree in tvZsmTree.ItemsSource){tree.IsExpanded = true;tree.SetChildrenExpanded(true);}}/// <summary>/// 全部折疊菜單事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void menuUnExpandAll_Click(object sender, RoutedEventArgs e){foreach (Model.TreeModel tree in tvZsmTree.ItemsSource){tree.IsExpanded = false;tree.SetChildrenExpanded(false);}}/// <summary>/// 全部選中事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void menuSelectAll_Click(object sender, RoutedEventArgs e){foreach (Model.TreeModel tree in tvZsmTree.ItemsSource){tree.IsChecked = true;tree.SetChildrenChecked(true);}}/// <summary>/// 全部取消選中/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void menuUnSelectAll_Click(object sender, RoutedEventArgs e){foreach (Model.TreeModel tree in tvZsmTree.ItemsSource){tree.IsChecked = false;tree.SetChildrenChecked(false);}}/// <summary>/// 鼠標右鍵事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>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;}} }
在使用控件的時候,要在xaml中引入命名控件(根據實際引入)
xmlns:my="clr-namespace:Com.FMS.View.UserControls"
<!--使用控件-->
<my:ZsmTreeView x:Name="ztvModule" />?
ztvModule.ItemsSourceData = treeList;//treeList為IList<TreeModel>類型
??
本文轉自?http://www.cnblogs.com/zsmhhfy/archive/2013/03/18/2965755.html