WPF的Treeview控件的一般用法书上都有介绍,就没必要多讲。这里主要说明TreeView里实现CheckBox。
首先构造一个Node类
public class Node : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public Node()
{
this.IsSelected = false;
this.Nodes = new List<Node>();
}
/// <summary>
/// 节点名称
/// </summary>
public string NodeName { get; set; }
/// <summary>
/// 被删除
/// </summary>
private bool? isSelected = false;
public bool? IsSelected
{
set
{
this.isSelected = value;
this.NotifyPropertyChanged("IsSelected");
}
get { return this.isSelected; }
}
/// <summary>
/// 子节点集合
/// </summary>
public List<Node> Nodes { get; set; }
}
public enum NodeType
{
RootNode,//根节点
LeafNode,//叶子节点
}
接着来看一下后台数据,这里需要让TreeView的节点自动展开,并实现父节点被选,子节点全被选,父节点不选,子节点全部不选的功能(这里应该有更好的办法,我这里是用父节点的名称来判断的,对于指定的TreeView数据还好说)。
public partial class MainWindow : Window
{
public List<Node> nodeList { get; set; }
public MainWindow()
{
InitializeComponent();
}
private List<Node> GetNodeList()
{
Node leafOneNode = new Node();
leafOneNode.NodeName = "叶子节点一";
leafOneNode.Nodes = new List<Node>();
Node leafTwoNode = new Node();
leafTwoNode.NodeName = "叶子节点二";
leafTwoNode.Nodes = new List<Node>();
Node leafThreeNode = new Node();
leafThreeNode.NodeName = "叶子节点三";
leafThreeNode.Nodes = new List<Node>();
Node leafOneNode1 = new Node();
leafOneNode1.NodeName = "叶子节点1";
leafOneNode1.Nodes = new List<Node>();
Node leafTwoNode2 = new Node();
leafTwoNode2.NodeName = "叶子节点2";
leafTwoNode2.Nodes = new List<Node>();
Node leafThreeNode3 = new Node();
leafThreeNode3.NodeName = "叶子节点3";
leafThreeNode3.Nodes = new List<Node>();
return new List<Node>()
{
new Node(){NodeName="根节点",Nodes=new List<Node>(){leafOneNode, leafTwoNode, leafThreeNode}},
new Node(){NodeName="根节点1",Nodes=new List<Node>(){leafOneNode1, leafTwoNode2, leafThreeNode3}}
};
}
private void ExpandTree()
{
if (this.TreeView_NodeList.Items != null && this.TreeView_NodeList.Items.Count > 0)
{
foreach (var item in this.TreeView_NodeList.Items)
{
DependencyObject dependencyObject = this.TreeView_NodeList.ItemContainerGenerator.ContainerFromItem(item);
if (dependencyObject != null)//第一次打开程序,dependencyObject为null,会出错
{
((TreeViewItem)dependencyObject).ExpandSubtree();
}
}
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
nodeList = GetNodeList();
this.TreeView_NodeList.ItemsSource = nodeList;
ExpandTree();
}
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
if ((sender as CheckBox).Content.ToString() == "根节点")
{
foreach (Node item in nodeList[0].Nodes)
{
item.IsSelected = true;
}
}
else if ((sender as CheckBox).Content.ToString() == "根节点1")
{
foreach (Node item in nodeList[1].Nodes)
{
item.IsSelected = true;
}
}
else
{
if (nodeList[0].Nodes.Exists(x=>x.NodeName== (sender as CheckBox).Content.ToString()))
{
if (nodeList[0].Nodes.All(x => x.IsSelected== true))
{
nodeList[0].IsSelected = true;
}
else
nodeList[0].IsSelected = null;
}
if (nodeList[1].Nodes.Exists(x => x.NodeName == (sender as CheckBox).Content.ToString()))
{
if (nodeList[1].Nodes.All(x => x.IsSelected == true))
{
nodeList[1].IsSelected = true;
}
else
nodeList[1].IsSelected = null;
}
}
}
private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
{
if ((sender as CheckBox).Content.ToString() == "根节点")
{
foreach (Node item in nodeList[0].Nodes)
{
item.IsSelected = false;
}
}
else if ((sender as CheckBox).Content.ToString() == "根节点1")
{
foreach (Node item in nodeList[1].Nodes)
{
item.IsSelected = false;
}
}
else
{
if (nodeList[0].Nodes.Exists(x => x.NodeName == (sender as CheckBox).Content.ToString()))
{
if (nodeList[0].Nodes.All(x => x.IsSelected == false))
{
nodeList[0].IsSelected = false;
}
else
nodeList[0].IsSelected = null;
}
if (nodeList[1].Nodes.Exists(x => x.NodeName == (sender as CheckBox).Content.ToString()))
{
if (nodeList[1].Nodes.All(x => x.IsSelected == false))
{
nodeList[1].IsSelected = false;
}
else
nodeList[1].IsSelected = null;
}
}
}
}
前台的xaml代码:
<Grid>
<TreeView Name="TreeView_NodeList">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Node}" ItemsSource="{Binding Nodes,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
<StackPanel Orientation="Horizontal" Margin="0,2,0,2">
<CheckBox Content="{Binding NodeName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" ToolTip="{Binding NodeName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" IsChecked="{Binding IsSelected,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked" ></CheckBox>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
或许这里可以用Style来做,暂时解决问题先就这样,因为代码也不长。