2013-08-23 10 views
7

Próbuję ustawić właściwość moich TreeView przedmiotów przy użyciu szablonu warunkową IsExpanded w XAML:Ustawianie IsExpanded na WPF TreeViewItem z DataTrigger

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

Kiedy ustawić właściwość z C# MyStatus kod, kolory są zmieniane (tak, że działa DataTrigger), ale węzły nie są rozwinięte.

_myItems[0].MyStatus = MyStatus.Opened; 

Jak mogę ustawić właściwość od A DataTriggerTreeViewItem.IsExpanded?

Kiedy uruchomić aplikację, kolory są prawidłowo ustawione, ale zielona węzeł nie zostanie rozszerzony:

Screenshot just after starting the application

I po zmianie wartości _myItems[0].MyStatus i _myItems[1].MyStatus, kolory są odpowiednio zmieniane , ale zielony węzeł nadal nie jest rozwinięty.

Screenshot after clicking the Button1

Pełna Code (XAML)

pełny kod jest nieco długa, ale to 90% boilerplate.

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

pełny kod (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

Powiązane: [Widok drzewa WPF DataBound expand/collapse] (http://stackoverflow.com/q/1717654/324969), ale używają 'Style' podczas używania' DataTrigger'. –

Odpowiedz

9

Istnieje kilka rzeczy źle tutaj. Po pierwsze ustawiasz właściwość TreeViewItem.IsSelected na HierarchicalDataTemplate. To nie zadziała. Zamiast tego będziesz musiał ustawić ItemContainerStyle na TreeView:

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

Nie można po prostu umieścić Trigger tu jednak. Z powodu DependencyProperty value precedence, jeśli użytkownik kliknie na węzły, aby je rozwinąć lub zwinąć, wyzwalacze nie będą numerem 1 na liście priorytetów (jest to wartość lokalna). Dlatego najlepiej jest utworzyć nowy IValueConverter, aby przekonwertować z MyStatus na bool. A następnie Skonfiguruj TwoWay wiążące w Setter w Style:

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

i Twojego konwertera:

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

Dzięki, ostatecznie użyłem bezpośrednio właściwości Boolean 'MyExpanded' oprócz pola wyliczeniowego' MyStatus', aby uniknąć konwertera ("Konwertowanie" byłoby problematyczne, ponieważ w wyliczeniu są więcej niż dwie wartości). –

1

musiałem zrobić coś podobnego, a ja rozwiązać to w ten sposób:

<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 Borro la podkład parte: –

+0

+3

przepełnienie stosu nie jest wielojęzyczna strona. Proszę pisać po angielsku. –