从 TreeViewItem 的 ItemSource 读取 "IsExpanded" 属性
Reading the "IsExpanded" property from the ItemSource of a TreeViewItem
所以我希望 TreeView 项的 IsExpanded 属性 反映在数据上下文中。
<TreeView x:Name="TreeViewMonitorEvents" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Grid.Column="0" Grid.Row="1" Grid.RowSpan="5"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=Page}, Path=MonitorEventCatagories}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type tree:TreeGroup}" ItemsSource="{Binding Members}" >
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" MouseMove="DragDrop_MouseMove_TreeGroup">
<CheckBox Name="CheckboxTreeGroup" IsChecked="{Binding Path=(tree:TreeItemHelper.IsChecked), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Template="{DynamicResource MonitoringUICheckBox}" Style="{StaticResource MonitoringUICheckBoxStyling}"
MouseMove="DragDrop_MouseMove_TreeGroup" Checked="CheckboxTreeGroup_Checked" Unchecked="CheckboxTreeGroup_Unchecked">
</CheckBox>
<TextBlock Text="{Binding Name}" Style="{StaticResource MonitorUIText}" MouseMove="DragDrop_MouseMove_TreeGroup"/>
</StackPanel>
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}" >
<Setter Property="IsExpanded" Value="{Binding IsExpanded,Mode=TwoWay}" />
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
</HierarchicalDataTemplate>
即 TreeGroup Class。在这里查看树组:
namespace RTX64MonitorUtility.TreeView
{
//Data class. Holds information in the Datacontext section of the UI Elements it is attached to.
public class TreeGroup : DependencyObject, IParent<object>
{
public string Name { get; set; }
public List<TreeMonitoringEvent> Members { get; set; }
public IEnumerable<object> GetChildren()
{
return Members;
}
public bool IsExpanded { get; set; } = false;
}
}
这是它从中提取的列表:
namespace RTX64MonitorUtility.Pages
{
/// <summary>
/// Interaction logic for EventsAndTriggers.xaml
/// </summary>
public partial class EventsAndTriggers : Page
{
public ObservableCollection<TreeGroup> MonitorEventCatagories { get; set; }
...
}
}
我的主要目标是,如果 TreeGroup 项未展开,则不会触发孩子的 Checked
和 Unchecked
事件,因此我需要为他们执行所需的操作。如果我能找到一种从这些事件中读取 IsExpanded
值的方法,那也是一个解决方案。
您通常通过使用以项目容器为目标的 Style
将项目容器的属性(如 TreeViewItem.IsExpanded
或 ListBoxItem.IsSelected
等)绑定到您的数据模型。 item容器的DataContext
是数据模型:
<TreeView>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
接下来,正确实现数据模型。作为数据绑定源的属性必须作为依赖属性(对于依赖对象)实现或引发 INotifyPropertyChanged.PropertyChanged
事件。
由于 DependencyObject
扩展了 DispatcherObject
,任何扩展 DependencyObject 的 class 都是线程仿射的:在 WPF 中,DispatcherObject
只能由与其关联的 Dispatcher 访问与.
出于这个原因,您通常更喜欢 INotifyPropertyChanged
数据模型。
DependencyObject
用于根据定义绑定到 Dispatcher
线程的 UI 个对象。
// Let the model implement the INotifyPropertyChanged interface
public class TreeGroup : INotifyPropertyChanged, IParent<object>
{
// Follow this pattern for all properties that will change
// and are source of a data binding.
private bool isExpanded;
public IsExpanded
{
get => this.isExpanded;
set;
{
this.isExpanded = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "")
=> this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
所以我希望 TreeView 项的 IsExpanded 属性 反映在数据上下文中。
<TreeView x:Name="TreeViewMonitorEvents" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Grid.Column="0" Grid.Row="1" Grid.RowSpan="5"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=Page}, Path=MonitorEventCatagories}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type tree:TreeGroup}" ItemsSource="{Binding Members}" >
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" MouseMove="DragDrop_MouseMove_TreeGroup">
<CheckBox Name="CheckboxTreeGroup" IsChecked="{Binding Path=(tree:TreeItemHelper.IsChecked), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Template="{DynamicResource MonitoringUICheckBox}" Style="{StaticResource MonitoringUICheckBoxStyling}"
MouseMove="DragDrop_MouseMove_TreeGroup" Checked="CheckboxTreeGroup_Checked" Unchecked="CheckboxTreeGroup_Unchecked">
</CheckBox>
<TextBlock Text="{Binding Name}" Style="{StaticResource MonitorUIText}" MouseMove="DragDrop_MouseMove_TreeGroup"/>
</StackPanel>
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}" >
<Setter Property="IsExpanded" Value="{Binding IsExpanded,Mode=TwoWay}" />
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
</HierarchicalDataTemplate>
即 TreeGroup Class。在这里查看树组:
namespace RTX64MonitorUtility.TreeView
{
//Data class. Holds information in the Datacontext section of the UI Elements it is attached to.
public class TreeGroup : DependencyObject, IParent<object>
{
public string Name { get; set; }
public List<TreeMonitoringEvent> Members { get; set; }
public IEnumerable<object> GetChildren()
{
return Members;
}
public bool IsExpanded { get; set; } = false;
}
}
这是它从中提取的列表:
namespace RTX64MonitorUtility.Pages
{
/// <summary>
/// Interaction logic for EventsAndTriggers.xaml
/// </summary>
public partial class EventsAndTriggers : Page
{
public ObservableCollection<TreeGroup> MonitorEventCatagories { get; set; }
...
}
}
我的主要目标是,如果 TreeGroup 项未展开,则不会触发孩子的 Checked
和 Unchecked
事件,因此我需要为他们执行所需的操作。如果我能找到一种从这些事件中读取 IsExpanded
值的方法,那也是一个解决方案。
您通常通过使用以项目容器为目标的 Style
将项目容器的属性(如 TreeViewItem.IsExpanded
或 ListBoxItem.IsSelected
等)绑定到您的数据模型。 item容器的DataContext
是数据模型:
<TreeView>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
接下来,正确实现数据模型。作为数据绑定源的属性必须作为依赖属性(对于依赖对象)实现或引发 INotifyPropertyChanged.PropertyChanged
事件。
由于 DependencyObject
扩展了 DispatcherObject
,任何扩展 DependencyObject 的 class 都是线程仿射的:在 WPF 中,DispatcherObject
只能由与其关联的 Dispatcher 访问与.
出于这个原因,您通常更喜欢 INotifyPropertyChanged
数据模型。
DependencyObject
用于根据定义绑定到 Dispatcher
线程的 UI 个对象。
// Let the model implement the INotifyPropertyChanged interface
public class TreeGroup : INotifyPropertyChanged, IParent<object>
{
// Follow this pattern for all properties that will change
// and are source of a data binding.
private bool isExpanded;
public IsExpanded
{
get => this.isExpanded;
set;
{
this.isExpanded = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "")
=> this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}