简体   繁体   English

从 TreeViewItem 的 ItemSource 读取“IsExpanded”属性

[英]Reading the "IsExpanded" property from the ItemSource of a TreeViewItem

So I want the IsExpanded Property of the TreeView Item so be reflected in the datacontext.所以我希望 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>

Ie the TreeGroup Class. See Treegroup here:即 TreeGroup Class。请在此处查看 Treegroup:

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;
    }
}

Here is the List it's drawing from:这是它从中绘制的列表:

namespace RTX64MonitorUtility.Pages
{
    /// <summary>
    /// Interaction logic for EventsAndTriggers.xaml
    /// </summary>
    public partial class EventsAndTriggers : Page
    {
         public ObservableCollection<TreeGroup> MonitorEventCatagories { get; set; }
         ...
    }
}

My primary goal here is that if the TreeGroup Item is not expanded then the chidren's Checked and Unchecked events do not get triggered so I need to do the required actions for them.我的主要目标是,如果 TreeGroup Item 没有展开,那么孩子的CheckedUnchecked事件就不会被触发,所以我需要为他们执行所需的操作。 If I can find out a way of reading the IsExpanded value from those events that would also be a solution.如果我能找到一种从这些事件中读取IsExpanded值的方法,那也是一种解决方案。

You usually bind the item container's properties like TreeViewItem.IsExpanded or ListBoxItem.IsSelected etc. to your data model by using a Style that targets the item container.您通常通过使用以项目容器为目标的Style将项目容器的属性(如TreeViewItem.IsExpandedListBoxItem.IsSelected等)绑定到数据 model。 The DataContext of the item container is the data model: item容器的DataContext是数据model:

<TreeView>
  <TreeView.ItemContainerStyle>
    <Style TargetType="TreeViewItem">
      <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
    </Style>
  </TreeView.ItemContainerStyle>
</TreeView>

Next, implement the data model properly.接下来正确实现数据model。 The properties that are the source of the data binding must be implemented as dependency properties (for dependency objects) or raise INotifyPropertyChanged.PropertyChanged event.作为数据绑定源的属性必须作为依赖属性(对于依赖对象)实现或引发INotifyPropertyChanged.PropertyChanged事件。

Since DependencyObject extends DispatcherObject , any class that extends DependencyObject is thread affine: in WPF, a DispatcherObject can only be accessed by the Dispatcher it is associated with.由于DependencyObject扩展了DispatcherObject ,任何扩展 DependencyObject 的 class 都是线程仿射的:在 WPF 中, DispatcherObject只能由与其关联的 Dispatcher 访问。
For this reason you usually prefer INotifyPropertyChanged on data models.出于这个原因,您通常更喜欢在数据模型上使用INotifyPropertyChanged
DependencyObject is for UI objects that are bound to the Dispatcher thread by definition. 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));
  }
}

See Microsoft Docs: Data binding overview (WPF .NET)请参阅Microsoft 文档:数据绑定概述 (WPF .NET)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM