wpf 获取在树视图中选择的节点

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11981402/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 04:59:12  来源:igfitidea点击:

Get the nodes selected in treeview

c#wpftreeview

提问by Ramesh Durai

I have a custom treeview class in WPF. I wanted to get the selected nodes text in a string list.

我在 WPF 中有一个自定义的树视图类。我想在字符串列表中获取选定的节点文本。

Rules:

规则:

  • If all the nodes in parent is selected, then return the parent node text alone.
  • If all the nodes in parent is not selected, then return a list of parentName_childNameof the nodes which is selected.

    The above two rules will apply for all levels. For a treeview with 2 levels of hierarchy return the name as parentName_child1Name_child1ChildName.

  • 如果父节点中的所有节点都被选中,则单独返回父节点文本。
  • 如果未选择 parent 中的所有节点,则返回parentName_childName所选节点的列表。

    以上两条规则适用于所有级别。对于具有 2 个层次结构的树视图,将名称返回为parentName_child1Name_child1ChildName.

Node template c# code:

节点模板 c# 代码:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace TreeViewCheckBox
{
    public struct CheckBoxId
    {
        public static string IDCheckBox;
    }

    public class Node : INotifyPropertyChanged
    {
        private readonly ObservableCollection<Node> children = new ObservableCollection<Node>();    
        private readonly ObservableCollection<Node> parent = new ObservableCollection<Node>();
        private bool? isChecked = true;
        private bool isExpanded;
        private string text;

        public Node()
        {
            this.Id = Guid.NewGuid().ToString();
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public ObservableCollection<Node> Children
        {
            get { return this.children; }
        }
        public string Id { get; set; }
        public bool? IsChecked
        {
            get { return this.isChecked; }
            set
            {
                this.isChecked = value;
                this.RaisePropertyChanged("IsChecked");
            }
        }
        public bool IsExpanded
        {
            get { return this.isExpanded; }
            set
            {
                this.isExpanded = value;
                this.RaisePropertyChanged("IsExpanded");
            }
        }       
        public ObservableCollection<Node> Parent
        {
            get { return this.parent; }
        }
        public string Text
        {
            get { return this.text; }
            set
            {
                this.text = value;
                this.RaisePropertyChanged("Text");
            }
        }
        private void CheckedTreeChild(IEnumerable<Node> items, int countCheck)
        {
            bool isNull = false;
            foreach (Node paren in items)
            {
                foreach (Node child in paren.Children)
                {
                    if (child.IsChecked == true || child.IsChecked == null)
                    {
                        countCheck++;
                        if (child.IsChecked == null)
                        {
                            isNull = true;
                        }
                    }
                }
                if (countCheck != paren.Children.Count && countCheck != 0)
                {
                    paren.IsChecked = null;
                }
                else if (countCheck == 0)
                {
                    paren.IsChecked = false;
                }
                else if (countCheck == paren.Children.Count && isNull)
                {
                    paren.IsChecked = null;
                }
                else if (countCheck == paren.Children.Count && !isNull)
                {
                    paren.IsChecked = true;
                }

                if (paren.Parent.Count != 0)
                {
                    this.CheckedTreeChild(paren.Parent, 0);
                }
            }
        }
        private void CheckedTreeChildMiddle(
            IEnumerable<Node> itemsParent, IEnumerable<Node> itemsChild, bool? isCheckBoxChecked)
        {
            const int CountCheck = 0;
            this.CheckedTreeParent(itemsChild, isCheckBoxChecked);
            this.CheckedTreeChild(itemsParent, CountCheck);
        }
        private void CheckedTreeParent(IEnumerable<Node> items, bool? isCheckBoxChecked)
        {
            foreach (Node item in items)
            {
                item.IsChecked = isCheckBoxChecked;
                if (item.Children.Count != 0)
                {
                    this.CheckedTreeParent(item.Children, isCheckBoxChecked);
                }
            }
        }
        private void RaisePropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }

            const int CountCheck = 0;
            if (propertyName == "IsChecked")
            {
                if (this.Id == CheckBoxId.IDCheckBox && this.Parent.Count == 0 && this.Children.Count != 0)
                {
                    this.CheckedTreeParent(this.Children, this.IsChecked);
                }

                if (this.Id == CheckBoxId.IDCheckBox && this.Parent.Count > 0 && this.Children.Count > 0)
                {
                    this.CheckedTreeChildMiddle(this.Parent, this.Children, this.IsChecked);
                }

                if (this.Id == CheckBoxId.IDCheckBox && this.Parent.Count > 0 && this.Children.Count == 0)
                {
                    this.CheckedTreeChild(this.Parent, CountCheck);
                }
            }
        }
    }
}

UserControl XAML code:

用户控件 XAML 代码:

<UserControl x:Class="TreeViewCheckBox.CustomTreeView"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 xmlns:TreeViewWithImageCheckBox="clr-namespace:TreeViewCheckBox"
                 mc:Ignorable="d">
        <UserControl.Resources>
            <HierarchicalDataTemplate DataType="{x:Type TreeViewCheckBox:Node}" ItemsSource="{Binding Children}">
                <StackPanel Orientation="Horizontal">
                    <StackPanel.Margin>2</StackPanel.Margin>
                    <CheckBox Margin="1" IsChecked="{Binding IsChecked}"
                              PreviewMouseLeftButtonDown="CheckBox_PreviewMouseLeftButtonDown"
                              Uid="{Binding Id}" />
                    <TextBlock Margin="1" Text="{Binding Text}" />
                </StackPanel>
            </HierarchicalDataTemplate>
            <Style TargetType="TreeViewItem">
                <Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}" />
            </Style>
        </UserControl.Resources>
        <Grid>
            <TreeView Name="tvMain" Grid.ColumnSpan="2" x:FieldModifier="private" />
        </Grid>
</UserControl>

UserControl c# code:

用户控件 C# 代码:

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Linq;
using System.Windows.Controls;
namespace TreeViewCheckBox
{
    public partial class CustomTreeView
    {
        public CustomTreeView()
        {
            this.Nodes = new ObservableCollection<Node>();
            this.InitializeComponent();
            this.FillTree();
        }
        private ObservableCollection<Node> Nodes { get; set; }

        public void FillTree()
        {
            this.Nodes.Clear();
            for (int i = 0; i < 5; i++)
            {
                var level1Items = new Node { Text = " Level 1 Item " + (i + 1) };
                for (int j = 0; j < 2; j++)
                {
                    var level2Items = new Node { Text = " Level 2 Item " + (j + 1) };
                    level2Items.Parent.Add(level1Items);
                    level1Items.Children.Add(level2Items);
                    for (int n = 0; n < 2; n++)
                    {
                        var level3Items = new Node { Text = " Level 3 Item " + (n + 1) };
                        level3Items.Parent.Add(level2Items);
                        level2Items.Children.Add(level3Items);
                    }
                }

                this.Nodes.Add(level1Items);
            }

            this.tvMain.ItemsSource = this.Nodes;
        }

        private void CheckBox_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var currentCheckBox = (CheckBox)sender;
            CheckBoxId.IDCheckBox = currentCheckBox.Uid;
        }
    }
   }

How to get the selected nodes in a List?

如何获取列表中的选定节点?

采纳答案by Sandeep

Probably, you will have to traverse through the Nodes collection and check for value of the IsChecked property. Something like this:

您可能需要遍历 Nodes 集合并检查 IsChecked 属性的值。像这样的东西:

private List<string> SelectedNodes = new List<string>();

private void GetSelectedNodeText(NodeCollection nodes)
{
    foreach (Node node in nodes)
    {
        if (node.IsChecked != true && node.IsChecked != false)
        {
            SelectedNodes.Add(node.Text + "_" + GetSelectedChildNodeText(node.ChildNodes));
        }
        else if (node.IsChecked == true)
        {
            SelectedNodes.Add(node.Text);
        }
    }
}

private string GetSelectedChildNodeText(NodeCollection nodes)
{
    string retValue = string.Empty;

    foreach (Node node in nodes)
    {
        if (node.IsChecked != true && node.IsChecked != false)
        {
            retValue = node.Text + "_" + GetSelectedChildNodeText(node.ChildNodes);
        }
        else if (node.IsChecked == true)
        {
            retValue = node.Text;
        }
    }

    return retVal;
}

My assumptions:

我的假设:

  1. The IsChecked property has true value when all it's children are selected.
  2. The IsChecked property has false value when all it's children are de-selected.
  3. The IsChecked property has neither true nor false value when only some of it's children are selected.
  4. You have the node's Text in the Node.Text property.
  1. IsChecked 属性在它的所有子项都被选中时具有真值。
  2. 当取消选择所有子项时,IsChecked 属性具有 false 值。
  3. 当仅选择了 IsChecked 的某些子项时,IsChecked 属性既没有 true 也没有 false 值。
  4. 您在 Node.Text 属性中有节点的文本。

回答by Ramesh Durai

Thanks to Sandeep for his idea.

感谢 Sandeep 的想法。

The following code is working fine..

以下代码工作正常..

public List<string> GetSelectedNodes()
{
    var listNodes = new List<string>();
    foreach (Node node in this.Nodes)
    {
        if (node.IsChecked == null)
        {
            this.GetSelectedChildNodeText(node.Text, node.Children, ref listNodes);
        }
        else if (node.IsChecked == true)
        {
            listNodes.Add(node.Text);
        }
    }

    return listNodes;
}

private void GetSelectedChildNodeText(string nodeName, IEnumerable<Node> nodes, ref List<string> listNodes)
{
    foreach (Node node in nodes)
    {
        string currentName = string.Format("{0}_{1}", nodeName, node.Text);
        if (node.IsChecked == null)
        {
            this.GetSelectedChildNodeText(currentName, node.Children, ref listNodes);
        }
        else if (node.IsChecked == true)
        {
            listNodes.Add(currentName);
        }
    }
}