2010-11-04 2 views
9

У меня есть 3 datagrids, которые используют один и тот же тип данных. Я хотел бы настроить привязку столбцов один раз и использовать 3 ресурса данных.Могу ли я поделиться DataGrid.Columns среди таблиц DataGrid

например.

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

Есть ли способ, чтобы установить ItemsSource для каждого DataGrid, а затем использовать DataTemplate или ControlTemplate, чтобы получить столбцы?

+1

подобный вопрос, полезные ответы: http://stackoverflow.com/questions/5716123/wpf-datagrid-columns-in-style-or-resource – surfen

ответ

4

Да ... двумя способами. Один вы можете просто добавить стиль для DataGrid, который задает столбцы, как это ...

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

Это работает, но представляет собой проблему, если вы подаете его к нескольким сетям, которые сами по себе уже может использовать стиль.

В этом случае другой, более гибкий способ работает лучше. Однако это требует создания классов, совместимых с XAML, для представления ObservableCollection<DataGridColumn> (хотя вы технически только упомянутые столбцы, мне нравится быть полным, поэтому я бы тоже сделал это для строк). Затем добавьте их в место, которое вы можете ссылаться в XAML Пространства имен. (Я называю мое xmlns:dge для «DataGridEnhancements»), то Вы можете использовать его как этот:

В коде Somwhere (я бы сделать его доступным приложение шириной) ...

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

Тогда в ресурсах ...

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

И, наконец, в XAML ...

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

НТН,

Марк

EDIT: Поскольку вы не можете установить DataGrid.Columns свойство, необходимо повысить ваш DataGridView (как указано в комментариях). Вот код для 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); } 
     } 
    } 

Теперь вы можете установить столбцы с SetColumns свойства зависимостей созданы в 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

Действительно ли это работает? У свойства Columns нет сеттера: http://msdn.microsoft.com/en-us/library/system.windows.controls.datagrid.columns.aspx – surfen

+2

Ooops! Я думаю ты прав. Наш код работал, потому что мы использовали собственный подкласс под названием EnhancedDataGrid, который обрабатывал это. Он добавил сеттера, но только на самом деле перешел через детей. Я просто изменил имя класса из нашего подкласса в DataGrid для примера. Спасибо, что вызвали это. Самый простой способ сделать это - добавить второе свойство Collection и связать их содержимое внутри. Только незначительное изменение этого кода внутри сетки. – MarqueIV

+0

Спасибо, хорошее решение. Можете ли вы показать мне, как установить «стили» сетки на основе какого-либо свойства на моей модели просмотра. У меня разный макет, основанный на тех же данных. –

1

Вы можете создать настраиваемый элемент управления только для того, чтобы обернуть сетку данных и передать данные на нее. Элемент управления установит данные в сетке.

+0

Это работает только в том случае, если вся сетка одинакова между всеми итерациями, что может быть или не быть. Кроме того, это ограничивает возможность стирать их с помощью шаблонов управления или других стилей, так как вы завернули его в UserControl. @Queso специально спросила только о столбцах, поэтому я предложил вышеупомянутое решение, которое предназначено только для этого, и может использоваться везде, где вы используете сетку, в том числе в UserControl. – MarqueIV

0

Этот ответ основан на решении MarquelV в. В своем ответе (и в комментариях) он упоминает пользовательский контроль под названием EnhancedDataGrid, где он предоставляет логику DataGrid.Columns.Вот код для 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); } 
     } 
    } 

Теперь вы можете установить столбцы с SetColumns свойства зависимостей созданы в 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}" />