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;
}
}
}
選択したノードをリストで取得するには?