最近在学习wpf,习惯把自己学习的东西记下来。
刚开始接触的这个控件,有点不知道怎么用。网上看了下,好像大家都觉得不如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();
}
//////////////////////////////////////////////////////////////////////////
// 节点文字信息
public stringtext
{
get;
set;
}
// 节点其他信息
// ...
// 父节点
public TreeItemparent
{
get;
set;
}
// 子节点
public ObservableCollection children
{
get;
set;
}
//////////////////////////////////////////////////////////////////////////
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
namespace WPFTreeviewExamples
{
class TreeItem
{
// 构造函数
public TreeItem()
{
children= new ObservableCollection();
}
//////////////////////////////////////////////////////////////////////////
// 节点文字信息
public stringtext
{
get;
set;
}
// 节点其他信息
// ...
// 父节点
public TreeItemparent
{
get;
set;
}
// 子节点
public ObservableCollection 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>
<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;
}
// 节点其他信息
// ...
// 节点文字信息
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>
<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;
//////////////////////////////////////////////////////////////////////////
}
}
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>
<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;
}
{
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;
}