2010-11-04 2 views
9

J'ai trois Dataagrids qui partagent le même type de données. Je voudrais configurer la liaison de colonne une fois et avoir les 3 DataGrid partagent la ressource.Puis-je partager DataGrid.Columns entre les tables DataGrid?

par exemple.

 <DataGrid Grid.Row="1" x:Name="primaryDG" ItemsSource="{Binding Path=dgSource AutoGenerateColumns="False"> 
     <DataGrid.Columns> 
      <DataGridTextColumn Width="Auto" Header="Column 1" Binding="{Binding Path=Col1}"/> 
      <DataGridTextColumn Width="Auto" Header="Column 2" Binding="{Binding Path=Col2}"/> 
      <DataGridTextColumn Width="Auto" Header="Column 3" Binding="{Binding Path=Col3}"/> 
      <DataGridTextColumn Width="Auto" Header="Column 4" Binding="{Binding Path=Col4}"/> 
     </DataGrid.Columns> 
    </DataGrid> 

est-il un moyen de régler la ItemsSource pour chaque DataGrid, puis utiliser un DataTemplate ou ControlTemplate pour obtenir les colonnes?

+1

question similaire, des réponses utiles: http://stackoverflow.com/questions/5716123/wpf-datagrid-colonnes-dans-style-ou-ressource – surfen

Répondre

4

Oui ... deux façons. Un, vous pouvez simplement ajouter un style pour DataGrid qui définit les colonnes comme celui-ci ...

<Style x:Key="MyColumnDefsStyle" x:Shared="True" TargetType="DataGrid"> 
    <Setter Property="Columns"> 
     <Setter.Value> 
      <DataGridTextColumn Width="Auto" Header="Column 1" Binding="{Binding Path=Col1}"/> 
      <DataGridTextColumn Width="Auto" Header="Column 2" Binding="{Binding Path=Col2}"/> 
      <DataGridTextColumn Width="Auto" Header="Column 3" Binding="{Binding Path=Col3}"/> 
      <DataGridTextColumn Width="Auto" Header="Column 4" Binding="{Binding Path=Col4}"/> 
     </Setter.Value> 
    </Setter> 
</Style> 

<DataGrid Style="{StaticResource MyColumnDefsStyle}" ItemsSource="{Binding Foo1}" /> 
<DataGrid Style="{StaticResource MyColumnDefsStyle}" ItemsSource="{Binding Foo2}" /> 
<DataGrid Style="{StaticResource MyColumnDefsStyle}" ItemsSource="{Binding Foo3}" /> 

Cela fonctionne, mais représente un problème si vous l'appliquez à plusieurs grilles qui elles-mêmes peuvent déjà utiliser un style.

Dans ce cas, l'autre, plus flexible, fonctionne mieux. Cela nécessite toutefois de créer des classes compatibles XAML pour représenter un ObservableCollection<DataGridColumn> (bien que techniquement vous ayez seulement dit colonnes, j'aime être complet moi-même donc j'en ferais aussi un pour les lignes) Ensuite, ajoutez-les dans un endroit que vous pouvez référencer dans le XAML espaces de noms. (J'appelle le mien xmlns:dge pour « DataGridEnhancements ») Vous utilisez alors comme ceci:

Dans le code somwhere (je le rendre accessible l'application à l'échelle) ...

public class DataGridRowsCollection : ObservableCollection<DataGridRow>{} 
public class DataGridColumnsCollection : ObservableCollection<DataGridColumn>{} 

Puis, dans les ressources ...

<dge:DataGridColumnsCollection x:Key="MyColumnDefs" x:Shared="True"> 
    <DataGridTextColumn Width="Auto" Header="Column 1" Binding="{Binding Path=Col1}"/> 
    <DataGridTextColumn Width="Auto" Header="Column 2" Binding="{Binding Path=Col2}"/> 
    <DataGridTextColumn Width="Auto" Header="Column 3" Binding="{Binding Path=Col3}"/> 
    <DataGridTextColumn Width="Auto" Header="Column 4" Binding="{Binding Path=Col4}"/> 
</dge:DataGridColumnsCollection> 

Et enfin dans le XAML ...

<DataGrid Columns="{StaticResource MyColumnDefs}" ItemsSource="{Binding Foo1}" /> 
<DataGrid Columns="{StaticResource MyColumnDefs}" ItemsSource="{Binding Foo2}" /> 
<DataGrid Columns="{StaticResource MyColumnDefs}" ItemsSource="{Binding Foo3}" /> 

HTH,

Mark

EDIT: Puisque vous ne pouvez pas définir la propriété DataGrid.Columns, vous devez améliorer votreDataGridView (comme mentionné dans les commentaires). Voici le code pour un EnhancedDataGrid:

public class EnhancedDataGrid : DataGrid 
    { 
     //the dependency property for 'setting' our columns 
     public static DependencyProperty SetColumnsProperty = DependencyProperty.Register(
      "SetColumns", 
      typeof (ObservableCollection<DataGridColumn>), 
      typeof (EnhancedDataGrid), 
      new FrameworkPropertyMetadata 
      { 
       DefaultValue = new ObservableCollection<DataGridColumn>(), 
       PropertyChangedCallback = EnhancedDataGrid.SetColumnsChanged, 
       AffectsRender = true, 
       AffectsMeasure = true, 
       AffectsParentMeasure = true, 
       IsAnimationProhibited = true, 
       DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, 
      }); 

     //callback to reset the columns when our dependency property changes 
     private static void SetColumnsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      var datagrid = (DataGrid) d; 

      datagrid.Columns.Clear(); 
      foreach (var column in (ObservableCollection<DataGridColumn>)e.NewValue) 
      { 
       datagrid.Columns.Add(column); 
      } 
     } 

     //The dependency property wrapper (so that you can consume it inside your xaml) 
     public ObservableCollection<DataGridColumn> SetColumns 
     { 
      get { return (ObservableCollection<DataGridColumn>) this.GetValue(EnhancedDataGrid.SetColumnsProperty); } 
      set { this.SetValue(EnhancedDataGrid.SetColumnsProperty, value); } 
     } 
    } 

Maintenant, vous pouvez définir les colonnes avec la propriété SetColumns dépendance créée dans votre CustomControl:

<custom:EnhancedDataGrid SetColumns="{StaticResource MyColumnDefs}" ItemsSource="{Binding Foo1}" /> 
<custom:EnhancedDataGrid SetColumns="{StaticResource MyColumnDefs}" ItemsSource="{Binding Foo2}" /> 
<custom:EnhancedDataGrid SetColumns="{StaticResource MyColumnDefs}" ItemsSource="{Binding Foo3}" /> 
+1

Est-ce que ça marche vraiment? La propriété Columns n'a pas de paramètre: http://msdn.microsoft.com/fr-fr/library/system.windows.controls.datagrid.columns.aspx – surfen

+2

Oups! Je pense que tu as raison. Notre code a fonctionné parce que nous avons utilisé une sous-classe personnalisée appelée EnhancedDataGrid qui a traité cela. Il a ajouté le setter, mais seulement réellement déplacé sur les enfants. Je viens de changer le nom de classe de notre sous-classe à DataGrid pour l'exemple. Merci d'avoir appelé ça. La méthode la plus simple consiste à ajouter une deuxième propriété Collection et à lier leur contenu en interne. Seul un changement mineur de ce code dans la grille. – MarqueIV

+0

Merci bonne solution. Pouvez-vous me montrer comment définir les «styles» de la grille en fonction de certaines propriétés de mon viewmodel. J'ai une mise en page différente basée sur les mêmes données –

1

Vous pouvez créer un contrôle personnalisé simplement pour envelopper la grille de données et lui transmettre des données. Le contrôle va définir les données sur une grille.

+0

Cela ne fonctionne que si la grille entière est la même entre toutes les itérations, ce qui peut ou peut ne pas être le cas. De plus, cela limite la possibilité de les styliser avec des modèles de contrôle ou d'autres styles puisque vous les avez enveloppés dans un UserControl. @Queso spécifiquement posé des questions sur les colonnes, c'est pourquoi j'ai suggéré la solution ci-dessus qui ne cible que cela et peut être utilisé partout où vous utilisez une grille, y compris dans un UserControl. – MarqueIV

0

Cette réponse est basée sur la solution de MarquelV. Dans sa réponse (et dans les commentaires), il mentionne un contrôle personnalisé nommé EnhancedDataGrid, où il fournit la logique à définir la propriété DataGrid.Columns.Voici le code pour un EnhancedDataGrid:

public class EnhancedDataGrid : DataGrid 
    { 
     //the dependency property for 'setting' our columns 
     public static DependencyProperty SetColumnsProperty = DependencyProperty.Register(
      "SetColumns", 
      typeof (ObservableCollection<DataGridColumn>), 
      typeof (EnhancedDataGrid), 
      new FrameworkPropertyMetadata 
      { 
       DefaultValue = new ObservableCollection<DataGridColumn>(), 
       PropertyChangedCallback = EnhancedDataGrid.SetColumnsChanged, 
       AffectsRender = true, 
       AffectsMeasure = true, 
       AffectsParentMeasure = true, 
       IsAnimationProhibited = true, 
       DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, 
      }); 

     //callback to reset the columns when our dependency property changes 
     private static void SetColumnsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      var datagrid = (DataGrid) d; 

      datagrid.Columns.Clear(); 
      foreach (var column in (ObservableCollection<DataGridColumn>)e.NewValue) 
      { 
       datagrid.Columns.Add(column); 
      } 
     } 

     //The dependency property wrapper (so that you can consume it inside your xaml) 
     public ObservableCollection<DataGridColumn> SetColumns 
     { 
      get { return (ObservableCollection<DataGridColumn>) this.GetValue(EnhancedDataGrid.SetColumnsProperty); } 
      set { this.SetValue(EnhancedDataGrid.SetColumnsProperty, value); } 
     } 
    } 

Maintenant, vous pouvez définir les colonnes avec les SetColumns propriété de dépendance créée dans votre CustomControl:

<custom:EnhancedDataGrid SetColumns="{StaticResource MyColumnDefs}" ItemsSource="{Binding Foo1}" /> 
<custom:EnhancedDataGrid SetColumns="{StaticResource MyColumnDefs}" ItemsSource="{Binding Foo2}" /> 
<custom:EnhancedDataGrid SetColumns="{StaticResource MyColumnDefs}" ItemsSource="{Binding Foo3}" /> 
Questions connexes