У меня проблема. Мне нужно создать динамически создаваемый TreeListView с флажками. У меня это уже есть, но мне нужно автоматически выбрать все дочерние узлы, когда выбран родительский. Как мне это сделать? Это мой код, который я уже создал
[xml]$xaml = @"
<Window xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
Title = "My TreeView" Height = "300" Width = "300">
<Grid>
<TreeView Name = "MyTreeView" Margin = "10">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource = "{Binding Children}">
<StackPanel Orientation = "Horizontal">
<CheckBox IsChecked = "{Binding IsChecked, Mode=TwoWay}" VerticalAlignment = "Center"/>
<TextBlock Text = "{Binding Name}" Margin = "5,0,0,0"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Window>
"@
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$window=[Windows.Markup.XamlReader]::Load( $reader )
# Define the data structure for the treeview
class Node {
[string]$Name
[System.Collections.ObjectModel.ObservableCollection[Node]]$Children
[bool]$IsChecked
}
# Populate treeview with sample data
$root = New-Object Node
$root.Name = "Root"
$root.Children = New-Object System.Collections.ObjectModel.ObservableCollection[Node]
$child1 = New-Object Node
$child1.Name = "Child 1"
$child1.Children = New-Object System.Collections.ObjectModel.ObservableCollection[Node]
$child2 = New-Object Node
$child2.Name = "Child 2"
$child2.Children = New-Object System.Collections.ObjectModel.ObservableCollection[Node]
$root.Children.Add($child1)
$root.Children.Add($child2)
$treeview = $window.FindName("MyTreeView")
$treeview.ItemsSource = @($root)
$window.ShowDialog() | Out-Null
Как мне это сделать?
Добавьте некоторую логику в установщик свойства IsChecked
, который устанавливает соответствующее свойство всех элементов в коллекции Children
, и реализуйте интерфейс INotifyPropertyChanged
для уведомления представления:
Add-Type -TypeDefinition @"
using System.ComponentModel;
using System.Collections.ObjectModel;
public class Node : INotifyPropertyChanged {
public string Name { get; set; }
public ObservableCollection<Node> Children { get; set; }
private bool isChecked;
public bool IsChecked {
get { return isChecked; }
set {
isChecked = value;
OnPropertyChanged("IsChecked");
foreach (var node in Children)
node.IsChecked = true;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName) {
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
"@
Я модифицирую свой код и использую ваше решение, но мне нужно изменить одну вещь: node.IsChecked
должно быть установлено на value
, а не true
, потому что оно не будет работать, если не отмечено галочкой. Но у меня есть другая проблема. Я заполняю свое древовидное представление из xml. И его несколько вложенных. Когда я выбираю узел, и у этого узла есть дочерние элементы, он будет выбирать все узлы до тех пор, пока не появится первый узел с дочерними элементами.
прежде чем выбрать: после выбора корня:
[xml]$xaml = @"
<Window xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
Title = "My TreeView" Height = "300" Width = "300">
<Grid>
<TreeView Name = "MyTreeView" Margin = "10">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource = "{Binding Children}">
<StackPanel Orientation = "Horizontal">
<CheckBox IsChecked = "{Binding IsChecked, Mode=TwoWay}" VerticalAlignment = "Center"/>
<TextBlock Text = "{Binding Name}" Margin = "5,0,0,0"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Window>
"@
Add-Type -AssemblyName PresentationFramework
$reader=(New-Object System.Xml.XmlNodeReader $xaml)
$window=[Windows.Markup.XamlReader]::Load( $reader )
# Define the data structure for the treeview
Add-Type -TypeDefinition @"
using System.ComponentModel;
using System.Collections.ObjectModel;
public class Node : INotifyPropertyChanged {
public string Name { get; set; }
public ObservableCollection<Node> Children { get; set; }
private bool isChecked;
public bool IsChecked {
get { return isChecked; }
set {
isChecked = value;
OnPropertyChanged("IsChecked");
foreach (var node in Children)
node.IsChecked = value;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName) {
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
"@
$root = New-Object Node
$root.Name = "Root"
$root.Children = New-Object System.Collections.ObjectModel.ObservableCollection[Node]
function TreeView-AddValuesFromXml {
param($XmlNodes, $ParentItem)
foreach ($Node in $XmlNodes.ChildNodes) {
$Item = New-Object Node
$Item.Name = "$($Node.GetAttribute("ID")) - $($Node.GetAttribute("Name"))"
$Item.Children = New-Object System.Collections.ObjectModel.ObservableCollection[Node]
$ParentItem.Children.Add($Item)
if ($Node.HasChildNodes) {
TreeView-AddValuesFromXml -XmlNodes $Node -ParentItem $Item
}
}
}
$TreeView = $Window.FindName("TreeView")
$XmlPath = "\\path_toXML"
$Xml = [xml](Get-Content $XmlPath)
# Populate TreeView with XML data
TreeView-AddValuesFromXml -XmlNodes $Xml.DocumentElement -ParentItem $root
$treeview = $window.FindName("MyTreeView")
$treeview.ItemsSource = @($root)
$root.add_PropertyChanged({
})
$window.ShowDialog() | Out-Null
Обновлено: Задача решена. я добавить
$Item.add_PropertyChanged({
})
после
$ParentItem.Children.Add($Item)
Я не мог заставить это работать без добавления
Add-Type -AssemblyName PresentationFramework
.