1

WPF にカスタム ツリービュー クラスがあります。選択したノードのテキストを文字列リストで取得したかったのです。

ルール:

  • 親のすべてのノードが選択されている場合は、親ノードのテキストのみを返します。

  • 親のすべてのノードが選択されていない場合は、選択されparentName_childNameているノードのリストを返します。

    上記の 2 つのルールは、すべてのレベルに適用されます。2 レベルの階層を持つツリービューの場合、名前を として返しますparentName_child1Name_child1ChildName

ノード テンプレートの 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);
                }
            }
        }
    }
}

ユーザー コントロールの 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>

ユーザーコントロールの 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;
        }
    }
   }

選択したノードをリストで取得するには?

4

2 に答える 2

1

おそらく、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;
}

私の仮定:

  1. すべての子が選択されている場合、IsChecked プロパティの値は true になります。
  2. すべての子が選択解除されている場合、IsChecked プロパティの値は false になります。
  3. 子の一部のみが選択されている場合、IsChecked プロパティには true 値も false 値もありません。
  4. Node.Text プロパティにノードの Text があります。
于 2012-08-16T07:37:06.177 に答える
0

Sandeep のアイデアに感謝します。

次のコードは正常に動作しています..

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);
        }
    }
}
于 2012-08-16T09:42:29.790 に答える