在WPF中,专门有HierarchicalDataTemplate用于自定义显示TreeView和ListBox的层次结构,结合后台定义的数据,得以实现五花八门的外观。我现在先简要说明一下HierarchicalDataTemplate的使用方式:
1 public class DataItem 2 { 3 public string Header { get; set; } 4 public IList<DataItem> Childs { get; set; } 5 }
上面是树的一个结点类,包括了一个Header字段和子结点列表,下面则是对应的前台代码:
<Grid> <Grid.Resources> <HierarchicalDataTemplate x:Key="myDataTemplate" ItemsSource="{Binding Childs}"> <Label Content="{Binding Header}" /> </HierarchicalDataTemplate> </Grid.Resources> <TreeView x:Name="TV_Test" ItemTemplate="{StaticResource myDataTemplate}" /> </Grid>
注意到,HierarchicalDataTemplate的ItemsSource就是层叠显示的关键,它可以遍历对应数据的所有Childs字段,并显示成<Label ... />的形式。接下来,把DataItem类型的数据集合赋给TreeView控件的ItemSource就完成了树形结构的显示:
1 List<DataItem> dataList = new List<DataItem>(); 2 DataItem item1 = new DataItem { Header = "结点1" }; 3 item1.Childs = new List<DataItem>(); 4 item1.Childs.Add(new DataItem { Header = "结点1-1" }); 5 item1.Childs.Add(new DataItem { Header = "结点1-2" }); 6 dataList.Add(item1); 7 dataList.Add(new DataItem { Header = "结点2" }); 8 TV_Test.ItemsSource = dataList;
所得结果如下图所示:
上面只是一个简单的示例,实际上可以通过更改HierarchicalDataTemplate中的内容来自定义树形显示,如图片、颜色、大小、布局等等。为了使上面的数据类DataItem更为通用 ,我自己扩充了一个结点类,使用该类,基本就可以完成大部分的功能了。
通用树结点类
1 using System.Collections.Generic; 2 using System.Collections.ObjectModel; 3 using System.Linq; 4 5 namespace EntityFramework.Common 6 { 7 /// <summary> 8 /// 实现了INotifyPropertyChanged接口通知的轻量级基类 9 /// </summary> 10 public abstract class ObservableBase : INotifyPropertyChanged 11 { 12 public event PropertyChangedEventHandler PropertyChanged; 13 14 protected void RaisePropertyChanged(string propertyName) 15 { 16 if (PropertyChanged != null) 17 { 18 PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 19 } 20 } 21 } 22 23 /// <summary> 24 /// 树数据类 25 /// </summary> 26 public class TreeViewData : ObservableBase 27 { 28 #region 私有字段 29 30 private string _Header; 31 private object _Tag; 32 private TreeViewData _Parent; 33 private ObservableCollection<TreeViewData> _Childs = new ObservableCollection<TreeViewData>(); 34 35 #endregion 36 37 #region 公有属性 38 39 /// <summary> 40 /// 名字 41 /// </summary> 42 public string Header 43 { 44 get { return _Header; } 45 set { _Header = value; RaisePropertyChanged("Header"); } 46 } 47 48 /// <summary> 49 /// 标签 50 /// </summary> 51 public object Tag 52 { 53 get { return _Tag; } 54 set { _Tag = value; RaisePropertyChanged("Tag"); } 55 } 56 57 /// <summary> 58 /// 父项 59 /// </summary> 60 public TreeViewData Parent 61 { 62 get { return _Parent; } 63 set { _Parent = value; RaisePropertyChanged("Parent"); } 64 } 65 66 /// <summary> 67 /// 子项 68 /// </summary> 69 public ObservableCollection<TreeViewData> Childs 70 { 71 get { return _Childs; } 72 set { _Childs = value; RaisePropertyChanged("Childs"); } 73 } 74 75 #endregion 76 77 #region 方法函数 78 79 public TreeViewData() { } 80 81 public TreeViewData(string header) 82 { 83 _Header = header; 84 } 85 86 public TreeViewData(string header, object tag, TreeViewData parent = null) 87 { 88 _Header = header; 89 _Tag = tag; 90 _Parent = parent; 91 } 92 93 /// <summary> 94 /// 添加子元素 95 /// </summary> 96 /// <param name="childs">子元素</param> 97 /// <returns>个数</returns> 98 public void AddChild(TreeViewData child) 99 { 100 child.Parent = this; 101 _Childs.Add(child); 102 } 103 104 /// <summary> 105 /// 添加子元素集合 106 /// </summary> 107 /// <param name="childs">子元素</param> 108 /// <returns>个数</returns> 109 public int AddChilds(IEnumerable<TreeViewData> childs) 110 { 111 int nCount = 0; 112 foreach (TreeViewData item in childs) 113 { 114 AddChild(item); ++nCount; 115 } 116 return nCount; 117 } 118 119 /// <summary> 120 /// 将指定名称的所有子节点从父元素中移除 121 /// </summary> 122 /// <param name="parent">父元素</param> 123 /// <param name="name">子节点名称</param> 124 public void RemoveChilds(TreeViewData parent, string name) 125 { 126 for (int i = 0; i < parent.Childs.Count; ++i) 127 { 128 if (parent.Childs[i].Header == name) 129 parent.Childs.Remove(parent.Childs[i]); 130 } 131 } 132 133 public override string ToString() 134 { 135 return _Header; 136 } 137 138 #endregion 139 } 140 }
这个类实现了INotifyPropertyChanged接口,能够更好地实现前台数据刷新,并且只初始化得当,还可以直接往上追踪父结点,删除、添加子结点。
转载请注明原址:http://www.cnblogs.com/lekko/archive/2012/08/28/2660360.html