2009-07-29 8 views
0

Je me demande s'il était possible de changer le style d'une colonne dans une grille de données wpf en fonction du type d'élément de la collection ItemsSource.Style de cellule différent dans une datagrid wpf en fonction du type de données dans ItemsSource

J'ai un datagrid wpf de la boîte à outils wpf. Les lignes simples de la grille doivent être stylées en fonction du type d'élément de la collection ItemsSource. Tous les éléments sont donc du même type de classe de base, mais les colonnes de certains types dérivés doivent avoir une stylisation différente.

Est-ce possible?

Merci :-)

Répondre

2

Oui, il est possible de le faire de plusieurs façons. Celui que je voudrais écrire est votre propre "custom switch" convertisseur qui sélectionne une valeur en fonction du type d'entrée. Comme ceci:

public class TypeSwitchConverter : Dictionary<Type, object>, IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, .CultureInfo culture) 
    { 
     foreach (var mapping in this) 
     { 
      if (mapping.Key.IsAssignableFrom(value.GetType())) 
      { 
       return mapping.Value; 
      } 
     } 

     return null; 
    } 

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

Et puis utilisez une liaison pour la Style de l'élément de niveau supérieur dans le modèle de votre cellule, et utiliser le convertisseur ci-dessus pour que la liaison au besoin. Voici un exemple simplifié que les styles des éléments dans une ListBox utilisant:

<ListBox ItemsSource="{Binding}"> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding}"> 
        <TextBlock.Style> 
         <Binding> 
          <Binding.Converter> 
           <my:TypeSwitchConverter> 
            <Style x:Key="{x:Type cor:Int32}" TargetType="{x:Type TextBlock}"> 
             <Setter Property="Background" Value="Red" /> 
            </Style> 
            <Style x:Key="{x:Type cor:String}" TargetType="{x:Type TextBlock}"> 
             <Setter Property="Background" Value="Green" /> 
            </Style> 
            <Style x:Key="{x:Type sys:Uri}" TargetType="{x:Type TextBlock}"> 
             <Setter Property="Background" Value="Blue" /> 
            </Style> 
           </my:TypeSwitchConverter> 
          </Binding.Converter> 
         </Binding> 
        </TextBlock.Style> 
       </TextBlock> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 
+0

Merci pour la réponse rapide! Le problème est que je veux ajouter des contrôles différents dans un panneau de pile en fonction du type dans la collection d'éléments. Comment résoudriez-vous cela? Donc, en tant que si doit avoir ajouté un objet de contrôle différent en fonction du type dans ItemsCollection. –

+0

Ensuite, il suffit de lier la propriété ItemTemplate à l'aide de 'TypeSwitchConverter' ci-dessus à différents modèles. –

+0

En fait, désolé, une légère correction - vous ne serez pas capable de lier directement parce que vous n'aurez pas d'élément en cours lors de la définition de ItemTemplate. Vous définissez donc un ItemTemplate contenant un seul élément de tout type (par exemple ContentPresenter), puis liez la propriété Template de cet élément à l'aide d'un convertisseur de commutateur. –

4

Une solution WPF seule:

Je suis un peu en retard pour le parti, mais si quelqu'un d'autre essaie de faire quelque chose comme ça, il y a une seule solution WPF. Il n'y a pas de classe DataGridColumn qui directement chercher le DataTemplate proprement dit, mais nous pouvons indirectement utiliser un ContentPresenter comme ceci:

<Window.Resources> 
    <DataTemplate DataType="{x:Type models:Employee}"> 
     <Grid>...</Grid> 
    </DataTemplate> 

    <DataTemplate DataType="{x:Type models:Manager}"> 
     <Grid>...</Grid> 
    </DataTemplate> 
</Window.Resources> 

<DataGrid ... > 
    <DataGrid.Columns> 
     <DataGridTemplateColumn Header="MyColumn"> 
      <DataGridTemplateColumn.CellTemplate> 
       <DataTemplate> 
        <ContentPresenter Content="{Binding}" /> 
       </DataTemplate> 
      </DataGridTemplateColumn.CellTemplate> 
     </DataGridTemplateColumn> 
    </DataGrid.Columns> 
</DataGrid> 

En intercalant un ContentPresenter dans un DataTemplate à l'intérieur du CellTemplate, nous obtenons le résultat souhaité .

+0

Grande solution, mais est-il possible de l'étendre à plus d'une colonne? Comment pourrions-nous sélectionner les «bons» modèles de données pour différentes colonnes (par exemple Titre et Subordonnées) si nous nous basons uniquement sur DataType? – mechanic

Questions connexes