2010-04-12 14 views
1

Je viens de remarquer un comportement étrange de TreeView de WPF. J'ai ajouté à la fois ItemContainerStyle pour lier à "IsSelected" de mon ViewModel et un ItemsTemplated pour l'affichage personnalisé de mes données. Mais maintenant, l'utilisateur ne peut plus changer le nœud sélectionné. À des fins de test, j'ai créé une interface utilisateur similaire en utilisant ListView et Expander. Cette version fonctionne comme excepté. Des conseils pour l'échec de TreeView?Comportement étrange WPF TreeView ItemContainerStyle et ItemTemplate

<TreeView ItemsSource="{Binding ElementName=frame, Path=list}"> 
     <TreeView.ItemContainerStyle> 
      <Style TargetType="{x:Type TreeViewItem}" > 
       <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/> 
      </Style> 
     </TreeView.ItemContainerStyle> 
     <TreeView.ItemTemplate> 
      <HierarchicalDataTemplate> 
       <TreeViewItem Header="{Binding}"> 
        <TextBlock Text="{Binding Path= Item.SomeData}"/> 
       </TreeViewItem> 
      </HierarchicalDataTemplate> 
     </TreeView.ItemTemplate> 
    </TreeView> 

EDIT: Mes données ne sont pas hiérarchiques. Je veux juste obtenir la fonctionnalité "effondrement" sur l'affichage d'une liste. Item.SomeData n'est pas une liste. L'affichage des données est comme souhaité. Seule la sélection par la souris échoue!

alt text http://img682.imageshack.us/img682/3702/bildy.png

+0

Qu'est-ce qui n'a pas fonctionné pour vous? Ou avez-vous déjà résolu votre problème? – Dabblernl

+0

Vous mettez un peu d'effort dans votre réponse. Mais ce n'est pas vraiment résoudre mon problème. J'ai édité ma question pour rendre mon problème plus compréhensible. – Matze

Répondre

3

TreeViews fonctionnent différemment. Les éléments à l'intérieur d'un HierarchicalDataTemplate sont TreeViewItems et tout contrôle que vous spécifiez dans le HierarchicalDataTemplate fonctionneront comme en-tête. Donc, fondamentalement, vous spécifiez que les éléments de votre TreeView sont TreeViewItems avec TreeViewItems comme en-têtes! Essayez plutôt ceci:

<HierarchicalDataTemplate ItemsSource="{Binding Items}"> 
     <Label Content="{Binding}"/> 
     <HierarchicalDataTemplate.ItemTemplate> 
     <DataTemplate> 
      <TextBlock Text="{Binding Path= Item.SomeData}"/> 
     </DataTemplate> 
     </HierarchicalDataTemplate.ItemTemplate> 
    </HierarchicalDataTemplate> 

EDIT: Je ne pouvais pas reproduire un DataSource qui produit les propriétés que vous souhaitez lier, j'ai donc écrit un code simple, de mon propre qui montre comment tout cela fonctionne. J'espère que vous serez en mesure de l'adapter à vos besoins:

<TreeView ItemsSource="{Binding}" Name="Tree"> 
      <TreeView.ItemContainerStyle> 
       <Style TargetType="{x:Type TreeViewItem}" > 
        <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/> 
       </Style> 
      </TreeView.ItemContainerStyle> 
      <TreeView.ItemTemplate> 
       <HierarchicalDataTemplate ItemsSource="{Binding Items}"> 
        <Label Content="{Binding Name}"/> 
        <HierarchicalDataTemplate.ItemTemplate> 
         <DataTemplate> 
          <TextBlock Text="{Binding Path= SomeData}"/> 
         </DataTemplate> 
        </HierarchicalDataTemplate.ItemTemplate> 
       </HierarchicalDataTemplate> 
      </TreeView.ItemTemplate> 
     </TreeView> 

using System.Collections.Generic; 
using System.ComponentModel; 
using System.Windows; 

namespace TreeViewSpike 
{ 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 
      List = new List<ItemList> 
         { 
          new ItemList 
           { 
            Name = "MyList", 
            Items = new List<Item> {new Item("1"), 
                  new Item("2")} 
           }, 
          new ItemList 
           { 
            Name = "MySecondList", 
            Items = new List<Item> {new Item("3"), 
                  new Item("4")} 
           } 
         }; 
      Tree.DataContext = List; 
      List[1].IsSelected = true; 
     } 

     public List<ItemList> List { get; set; } 
    } 

    public class ItemList: INotifyPropertyChanged 
    { 
     public string Name{ get; set;} 
     private bool _isSelected; 
     public bool IsSelected 
     { 
      get { return _isSelected; } 
      set 
      { 
       _isSelected = value; 
       if (PropertyChanged != null) 
        PropertyChanged(this, 
         new PropertyChangedEventArgs("IsSelected")); 
       if(_isSelected) 
        MessageBox.Show(Name + " selected"); 
      } 
     } 

     public List<Item> Items { get; set; } 
     public event PropertyChangedEventHandler PropertyChanged; 
    } 

    public class Item 
    { 
     public string SomeData { get; set; } 
     public Item(string data) 
     { 
      SomeData = data; 
     } 
    } 
}