2013-08-23 11 views
7

Ich versuche, die IsExpanded Eigenschaft meiner TreeView Artikel setzen eine bedingte Vorlage, in den XAML:Einstellung IsExpanded auf einer WPF TreeViewItem von einem Datatrigger

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

Wenn ich die MyStatus Eigenschaft aus dem # C eingestellt Code werden die Farben geändert (so funktioniert der DataTrigger), aber die Knoten werden nicht erweitert.

_myItems[0].MyStatus = MyStatus.Opened; 

Wie kann ich die TreeViewItem.IsExpanded Eigenschaft von einem DataTrigger?

Wenn ich die Anwendung starten, werden die Farben richtig eingestellt, aber die grüne Knoten nicht erweitert wird:

Screenshot just after starting the application

und nach dem Wert von _myItems[0].MyStatus und _myItems[1].MyStatus ändert, werden die Farben entsprechend geändert , aber der grüne Knoten ist immer noch nicht erweitert.

Screenshot after clicking the Button1

Voll-Code (XAML)

Der vollständige Code ist ein bisschen lang, aber es ist 90% vorformulierten.

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

Voll-Code (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)); 
      } 
     } 
    } 
} 
+0

Related: [WPF DataBound Treeview erweitern/reduzieren] (http://StackOverflow.com/q/1717654/324969), aber sie verwenden einen 'Style', während ich einen' DataTrigger' verwende. –

Antwort

9

Es gibt ein paar Dinge falsch hier. Der erste ist, dass Sie die Eigenschaft TreeViewItem.IsSelected auf eine HierarchicalDataTemplate setzen. Dies wird nicht funktionieren. Stattdessen wirst du eine ItemContainerStyle auf der TreeView einstellen müssen:

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

Sie können nicht nur die Trigger aber hier setzen. Aufgrund von DependencyProperty value precedence, wenn Ihr Benutzer auf die Knoten klickt, um sie zu erweitern oder zu reduzieren, sind Ihre Trigger nicht # 1 in der Rangfolge-Liste (das ist ein lokaler Wert). Daher ist es am besten, einen neuen IValueConverter zu erstellen, um von MyStatus in einen bool zu konvertieren. Und dann Setup ein TwoWay Bindung in einem Setter im Style:

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

und Ihr Konverter:

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

Danke, ich benutzte am Ende eine boolesche Eigenschaft 'MyExpanded' zusätzlich zum' MyStatus'-Enumerationsfeld, um den Konverter zu vermeiden (das 'ConvertBack' wäre problematisch, da es mehr als zwei Werte in der Enumeration gibt). –

1

Ich hatte etwas Ähnliches zu tun, und ich beschlossen, es auf diese Weise:

<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> 
+0

Perdón por algún motivo se Borró la Primer parte: –

+0

+3

Stack-Überlauf ist kein mehrsprachige Website. Bitte schreibe in Englisch. –