2010-11-04 12 views
9

Tengo 3 datagrids que comparten el mismo tipo de datos. Me gustaría configurar el enlace de la columna una vez y hacer que las 3 cuadrículas de datos compartan el recurso.Puedo compartir DataGrid.Columns entre las tablas de DataGrid

p. Ej.

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

¿Hay una manera de establecer el ItemsSource para cada cuadrícula de datos, a continuación, utilizar un DataTemplate o ControlTemplate para obtener las columnas?

+1

pregunta similar, respuestas útiles: http://stackoverflow.com/questions/5716123/wpf-datagrid-columns-in-style-or-resource – surfen

Respuesta

4

Sí ... dos formas. Uno simplemente puede añadir un estilo para DataGrid que establece las columnas como esta ...

<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}" /> 

que funciona, sino que representa un problema si lo está aplicando a múltiples redes que ellos mismos ya esté utilizando un estilo.

En ese caso, la otra forma, más flexible, funciona mejor. Sin embargo, esto requiere crear clases compatibles con XAML para representar un ObservableCollection<DataGridColumn> (aunque técnicamente solo dijiste columnas, me gustaría que se completara yo mismo, así que también haría una para las filas). Luego agrégalas a un lugar al que puedas hacer referencia en el XAML espacios de nombres (Que llamo mío xmlns:dge para 'DataGridEnhancements') A continuación se usa de esta manera:

En el código somwhere (me gustaría hacer accesible en todo el app) ...

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

Luego, en los recursos ...

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

Y finalmente en el XAML ...

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

HTH,

Marcos

EDIT: Puesto que no se puede establecer la propiedad DataGrid.Columns, es necesario mejorar su DataGridView (como se menciona en los comentarios). Este es el código para 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); } 
     } 
    } 

Ahora se podría establecer las columnas con los SetColumns propiedad de dependencia creado en su 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

¿Realmente funciona? La propiedad Columns no tiene setter: http://msdn.microsoft.com/en-us/library/system.windows.controls.datagrid.columns.aspx – surfen

+2

¡Ooops! Creo que tienes razón. Nuestro código funcionó porque usamos una subclase personalizada llamada EnhancedDataGrid que manejaba eso. Agregó el colocador, pero solo se movió sobre los niños. Acabo de cambiar el nombre de la clase de nuestra subclase a DataGrid para el ejemplo. Gracias por llamar a esto. La forma más sencilla de hacerlo es agregar una segunda propiedad de Colección y vincular sus contenidos internamente. Solo cambio menor de este código dentro de la grilla. – MarqueIV

+0

Gracias buena solución. ¿Puede mostrarme cómo configurar los "estilos" de la grilla en función de alguna propiedad en mi modelo de vista? Tengo un diseño diferente basado en los mismos datos –

1

Puede crear un control personalizado solo para envolver la cuadrícula de datos y pasarle datos. El control establecerá los datos en una grilla.

+0

Esto solo funciona si la cuadrícula completa es la misma entre todas las iteraciones, lo que puede o no ser el caso. Además, limita poder diseñarlos con plantillas de control u otros estilos también, ya que lo ha envuelto en un UserControl. @Queso preguntó específicamente sobre las columnas, por lo que sugerí la solución anterior, que solo se enfoca en eso y se puede usar en cualquier lugar donde se use una grilla, incluso dentro de un UserControl. – MarqueIV

0

Esta respuesta se basa en la solución de MarquelV. En su respuesta (y en los comentarios) menciona un control personalizado llamado EnhancedDataGrid, donde proporciona lógica a establece la propiedad DataGrid.Columns.Aquí está el código para 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); } 
     } 
    } 

Ahora se podría establecer las columnas con los SetColumns propiedad de dependencia creado en su 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}" /> 
Cuestiones relacionadas