2009-05-12 9 views
2

Le problème: Nous souhaitons lier la propriété ItemsSource d'un HierarchicalDataTemplate à un objet CollectionViewSource pour effectuer un regroupement et un filtrage. L'arrière-plan: Le problème original sur lequel nous travaillions avait à voir avec le filtrage d'un TreeView. Plus précisément, nous avons constaté que l'utilisation d'un filtre CollectionSource pour filtrer fonctionnait mais provoquait le repliement des nœuds TreeView. Cela est probablement dû au fait que la fonction Actualiser de la vue régénère sa liste d'objets, ce qui entraîne la régénération de ses nœuds par TreeView, ce qui entraîne la perte des états d'expansion des nœuds d'origine. Nous avons résolu ce problème en écrivant une classe similaire à CollectionViewSource mais en conservant la vue en éditant la liste d'objets afin qu'elle ne soit pas détruite lorsqu'elle change en raison du filtrage.Essayer de lier la propriété ItemsSource d'un HierarchicalDataTemplate à une CollectionViewSource (pour effectuer le groupage et le filtrage)

Cela a fonctionné parfaitement pour nous et nous aimerions l'utiliser à des niveaux plus profonds dans notre TreeView, ce qui nous ramène à notre problème. À l'heure actuelle, nous avons un HierarchicalDataTemplate qui ressemble à ceci:

<HierarchicalDataTemplate 

    x:Key="tableTemplate" 

    ItemsSource="{Binding Path=DataItems}" 

    ItemTemplateSelector="{StaticResource tableGroupsTemplateSelector}" 

    > 

Au lieu de cela, nous voulons se comporter comme ceci:

<HierarchicalDataTemplate 

    x:Key="tableTemplate" 

    ItemTemplateSelector="{StaticResource tableGroupsTemplateSelector}" 

    > 

    <HierarchicalDataTemplate.ItemsSource> 

     <Binding> 

      <Binding.Source> 

       <CollectionViewSource 

        Source="{Binding Path=DataItems}" 

        /> 

      </Binding.Source> 

     </Binding> 

    </HierarchicalDataTemplate.ItemsSource> 

Malheureusement, cette approche ne semble pas fonctionner. De ce que nous pouvons dire, la liaison dans le CVS ne se déclenche jamais; aucune erreur de liaison n'est déclenchée; Nous avons essayé d'attacher un convertisseur et de définir un point d'arrêt, mais le point d'arrêt n'a jamais été atteint. Nous avons également essayé diverses autres solutions, notamment: l'utilisation de RelativeSource, le déplacement de CollectionViewSource dans les ressources du modèle et l'incorporation de TreeViewItem dans le modèle. Cependant, rien n'a fonctionné. En passant, je me rends compte qu'une approche ViewModel permettrait le filtrage. Cependant, je suis à un endroit de notre cycle de développement où je ne peux pas faire ce genre de changement, donc je suis à la recherche d'alternatives, comme l'approche de CollectionViewSource.

Toute aide que vous pouvez donner serait appréciée.

Merci,

-Craig

Répondre

4

Dans mes applications j'ai trouvé que le moyen le plus simple pour atteindre le filtrage de l'arborescence est en liant la visibilité à une propriété sur les objets répertoriés.

Cette approche peut ne pas fonctionner pour vous mais si vous voulez l'essayer voici un exemple de ce que j'ai fait.

Dans les ressources de l'arborescence, vous ajoutez un déclencheur de style. vous pouvez lier le déclencheur à n'importe quelle propriété sur les objets que vous affichez, et vous pouvez ajouter dans un convertisseur de valeur si vous voulez ajouter une certaine logique pour inspecter l'élément et décider s'il doit être affiché ou non. Le déclencheur va réduire l'élément treeView si la propriété "Display" est false.

<TreeView.Resources> 
    <Style TargetType="TreeViewItem"> 
     <Style.Triggers> 
       <DataTrigger Binding="{Binding Path=Display}" Value="False"> 
        <Setter Property="Visibility" Value="Collapsed"/> 
       </DataTrigger> 
     </Style.Triggers> 
    </Style> 
</TreeView.Resources> 

Pour éviter d'ajouter un « affichage » propriété à vos objets, vous pouvez effectuer les opérations suivantes:

public class PositionVisibilityConverter : IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
     { 

      int positions = (int) value; 
      if (positions > 0) 
       return true; 
      return false; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      throw new System.NotSupportedException(); 
     } 
    } 

Et dans la reliure style TreeView ajouter le convertisseur de valeur:

<TreeView.Resources> 
    <Style TargetType="TreeViewItem"> 
     <Style.Triggers> 
       <DataTrigger Value="False"> 
        <Binding Path="Positions"> 
         <Binding.Converter> 
          <local:PositionVisibilityConverter/> 
         </Binding.Converter> 
        </Binding> 
        <Setter Property="Visibility" Value="Collapsed"/> 
       </DataTrigger> 
     </Style.Triggers> 
    </Style> 
</TreeView.Resources> 

Vous ne avez pas besoin pour spécifier le chemin si vous voulez inspecter l'objet entier.

Cette méthode a semblé fonctionner le mieux pour moi, essayez-le.

Questions connexes