摘要:[WPF] TreeView binding 處理打勾的範例
xaml 範例:
<TreeView ItemsSource="{Binding yourViewModelNodes}" VirtualizingStackPanel.IsVirtualizing="True">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="True"/>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type yourNamespace:yourNodeType}" ItemsSource="{Binding Nodes}">
<CheckBox IsChecked="{Binding CustomIsChecked}" Content="{Binding DisplayName}"
Command="{Binding DataContext.MyCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
CommandParameter="{Binding}"></CheckBox>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
打勾或不打勾連動子節點:
private void RecursiveChildren(Node current, bool isChecked)
{
foreach (var node in current.Nodes)
{
node.IsChecked = isChecked;
RecursiveChildren(node, isChecked);
}
}
打勾或不打勾連動父節點:
private void RecursiveParent(Node current, bool isChecked)
{
if (current == null)
return;
if (isChecked)
{
// 若有勾子節點,則是否全部子節點都勾了
current.IsChecked = current.Nodes.All(x => x.IsChecked == isChecked);
}
else
{
// 子節點一個沒勾,上面的父節點就不用勾了
current.IsChecked = false;
}
RecursiveParent(current.Parent, isChecked);
}
觸發打勾的 Command:
private RelayCommand _myCommand;
///
/// Gets the MyCommand.
///
public RelayCommand MyCommand
{
get
{
return _myCommand
?? (_myCommand = new RelayCommand(
p => DoCheckNodes(p)));
}
}
private void DoCheckNodes(Node selectedNode)
{
RecursiveChildren(selectedNode, selectedNode.IsChecked);
RecursiveParent(selectedNode.Parent, selectedNode.IsChecked);
}
得知被打勾的項目:
IEnumerable GetCheckedNodes(IEnumerable nodes)
{
foreach (var node in nodes)
{
// 傳回目前節點有打勾的,這邊依照自己想要的條件加入,或者加一個 Fun<T, bool>來判斷也行
if (node.IsChecked)
yield return node;
foreach (var children in GetCheckedNodes(node.Nodes))
{
yield return children;
}
}
}
這是工作要寫的內容,剛好前人寫得太複雜,
簡化一下處理樹狀打勾的方式。