c# – 从DataTrigger在WPF TreeViewItem上设置IsExpanded

我正在尝试使用条件模板在XAML中设置我的TreeView项的IsExpanded属性
<DataTrigger Binding="{Binding MyStatus}" Value="Opened">
    <Setter TargetName="MyTextBlock" Property="Foreground" Value="Green"/>
    <Setter Property="TreeViewItem.IsExpanded" Value="True" />
</DataTrigger>

当我从C#代码设置MyStatus属性时,颜色会更改(因此DataTrigger工作),但节点不会展开.

_myItems[0].MyStatus = MyStatus.Opened;

如何从DataTrigger设置TreeViewItem.IsExpanded属性

当我启动应用程序时,颜色已正确设置,但绿色节点未展开:

在更改_myItems [0] .MyStatus和_myItems [1] .MyStatus的值后,颜色会相应更改,但绿色节点仍未展开.

完整代码(XAML)

完整的代码有点长,但它是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>

完整代码(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));
            }
        }
    }
}

解决方法

这里有一些问题.第一个是您在HierarchicalDataTemplate上设置属性TreeViewItem.IsSelected.这不行.相反,您需要在TreeView上设置ItemContainerStyle:
<TreeView>
    <TreeView.ItemContainerStyle>
        <Style targettype="{x:Type TreeViewItem}">
        <!-- put logic for handling expansion here -->
        </Style>
    </TreeView.ItemContainerStyle>
</TreeView>

但是,你不能把Trigger放在这里.由于DependencyProperty value precedence,如果您的用户单击节点以展开或折叠它们,您的触发器将不会是优先级列表上的#1(即本地值).因此,您最好的选择是创建一个新的IValueConverter,以便从MyStatus转换为bool.然后在样式的Setter中设置TwoWay绑定:

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

而你的转换器:

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

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

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...