[英]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
,颜色也相应更改,但绿色节点仍未展开。
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>
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
: 然后在
Style
的Setter
中设置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.