[WPF] TreeView binding 處理打勾的範例

  • 1301
  • 0

摘要:[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;
                }
            }
        }

 

這是工作要寫的內容,剛好前人寫得太複雜,

簡化一下處理樹狀打勾的方式。