简体   繁体   English

从 DataTrigger 在 WPF TreeViewItem 上设置 IsExpanded

[英]Setting IsExpanded on a WPF TreeViewItem from a DataTrigger

I'm trying to set the IsExpanded property of my TreeView items using a conditional template, in the XAML :我正在尝试使用条件模板在XAML设置我的TreeView项目的IsExpanded属性:

<DataTrigger Binding="{Binding MyStatus}" Value="Opened">
    <Setter TargetName="MyTextBlock" Property="Foreground" Value="Green"/>
    <Setter Property="TreeViewItem.IsExpanded" Value="True" />
</DataTrigger>

When I set the MyStatus property from the C# code, the colors are changed (so the DataTrigger works), but the nodes aren't expanded.当我从 C# 代码设置MyStatus属性时,颜色会发生变化(因此 DataTrigger 可以工作),但不会展开节点。

_myItems[0].MyStatus = MyStatus.Opened;

How can I set the TreeViewItem.IsExpanded property from a DataTrigger ?如何从DataTrigger设置TreeViewItem.IsExpanded属性?

When I start the application, the colors are correctly set, but the green node isn't expanded:当我启动应用程序时,颜色设置正确,但绿色节点没有展开:

启动应用程序后的屏幕截图

And after changing the value of _myItems[0].MyStatus and _myItems[1].MyStatus , the colors are changed accordingly, but the green node still isn't expanded.并且更改_myItems[0].MyStatus_myItems[1].MyStatus ,颜色也相应更改,但绿色节点仍未展开。

单击 Button1 后的屏幕截图

Full Code (XAML)完整代码 (XAML)

The full code is a bit long, but it's 90% boilerplate.完整的代码有点长,但它是 90% 的样板。

<Window x:Class="WpfApplication6.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="150" Width="250">
    <DockPanel>
        <DockPanel.Resources>
            <HierarchicalDataTemplate ItemsSource="{Binding SubItems}" x:Key="MyTemplate">
                <StackPanel Orientation="Horizontal">
                    <!-- ... -->
                    <TextBlock x:Name="MyTextBlock" Foreground="Green" Text="{Binding Name}" />
                </StackPanel>

                <HierarchicalDataTemplate.Triggers>
                    <DataTrigger Binding="{Binding MyStatus}" Value="Closed">
                        <Setter TargetName="MyTextBlock" Property="Foreground" Value="Red"/>
                        <Setter Property="TreeViewItem.IsExpanded" Value="False" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding MyStatus}" Value="Opened">
                        <Setter TargetName="MyTextBlock" Property="Foreground" Value="Green"/>
                        <Setter Property="TreeViewItem.IsExpanded" Value="True" />
                    </DataTrigger>
                </HierarchicalDataTemplate.Triggers>
            </HierarchicalDataTemplate>
        </DockPanel.Resources>

        <Button Name="button1" Click="button1_Click" DockPanel.Dock="Top" Content="Button1"/>
        <TreeView Name="treeView1" ItemsSource="{Binding MyItems}" ItemTemplate="{StaticResource MyTemplate}"/>
    </DockPanel>
</Window>

Full Code (C#)完整代码 (C#)

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;

namespace WpfApplication6
{
    public partial class MainWindow : Window
    {
        private ObservableCollection<MyItemCollection> _myItems;

        public MainWindow() {
            InitializeComponent();

            _myItems = new ObservableCollection<MyItemCollection> {
                new MyItemCollection { Name = "Parent1", MyStatus = MyStatus.Closed, SubItems = { new MyItemCollection { Name = "Child1" } } },
                new MyItemCollection { Name = "Parent2", MyStatus = MyStatus.Opened, SubItems = { new MyItemCollection { Name = "Child2" } } }
            };

            DataContext = new {
                MyItems = _myItems
            };
        }

        private void button1_Click(object sender, RoutedEventArgs e) {
            _myItems[0].MyStatus = MyStatus.Opened;
            _myItems[1].MyStatus = MyStatus.Closed;
        }
    }

    public enum MyStatus
    {
        Closed,
        Opened
    }

    public class MyItemCollection : INotifyPropertyChanged
    {
        public MyItemCollection() {
            SubItems = new ObservableCollection<MyItemCollection>();
            _myStatus = MyStatus.Closed;
        }

        public string Name { get; set; }

        public ObservableCollection<MyItemCollection> SubItems { get; set; }

        private MyStatus _myStatus;
        public MyStatus MyStatus {
            get { return _myStatus; }
            set { _myStatus = value; NotifyPropertyChanged("MyStatus"); }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String propertyName) {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

There are a few things wrong here. 这里有一些问题。 The first is that you are setting the property TreeViewItem.IsSelected on a HierarchicalDataTemplate . 第一个是您在HierarchicalDataTemplate上设置属性TreeViewItem.IsSelected This won't work. 这不行。 Instead, you're going to need to set an ItemContainerStyle on the TreeView : 相反,您需要在TreeView上设置ItemContainerStyle

<TreeView>
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
        <!-- put logic for handling expansion here -->
        </Style>
    </TreeView.ItemContainerStyle>
</TreeView>

You can't just put the Trigger in here, however. 但是,你不能把Trigger放在这里。 Because of DependencyProperty value precedence , if your user clicks on the nodes to expand or collapse them, your triggers won't be #1 on the precedence list (that is a local value). 由于DependencyProperty值优先 ,如果用户单击节点以展开或折叠它们,则您的触发器将不会是优先级列表上的#1(即本地值)。 Therefore, your'e best bet is to create a new IValueConverter to convert from MyStatus to a bool . 因此,您最好的选择是创建一个新的IValueConverter以便从MyStatus转换为bool And then setup a TwoWay binding in a Setter in the Style : 然后在StyleSetter中设置TwoWay绑定:

<Style TargetType="{x:Type TreeViewItem}">
    <Setter Property="IsExpanded" 
            Value="{Binding MyStatus, Converter={StaticResource statusToBool}}" />
</Style>

And your converter: 而你的转换器:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    return ((MyStatus)value) == MyStatus.Opened;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
    return ((bool)value) ? MyStatus.Opened : MyStatus.Closed;
}

I had to do something similar, and I resolved it this way: 我不得不做类似的事情,我这样解决了:

<TreeView ItemsSource="{Binding source}"
          SnapsToDevicePixels="{Binding Path=myStatusToBool}"
          >
  <TreeView.ItemContainerStyle>
    <Style>
      <Setter Property="TreeViewItem.IsExpanded"
              Value="False"
              />
      <Style.Triggers>
        <DataTrigger Binding="{Binding Path=SnapsToDevicePixels,RelativeSource={RelativeSource AncestorType=TreeView}}"
                     Value="True">
            <Setter Property="TreeViewItem.IsExpanded"
                    Value="True"
                    />
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </TreeView.ItemContainerStyle>

  <TreeView.Resources>
  .....
  .....
  </TreeView.Resources>
</TreeView>

I Had the same issue, but solved it without a value converter:我遇到了同样的问题,但在没有值转换器的情况下解决了它:

                    <TreeView.ItemContainerStyle>
                        <Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}">
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding IsVisible}" Value="False">
                                    <Setter Property="Visibility" Value="Collapsed" />
                                </DataTrigger>
                                <DataTrigger Binding="{Binding IsExpanded}" Value="True">
                                    <Setter Property="IsExpanded" Value="True" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </TreeView.ItemContainerStyle>

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

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