Вот что я сделал, чтобы использовать это с шаблоном MVVM:
У меня есть два набора данных для привязки в моей модели представления: один для фактических данных сетки и один для заголовков столбцов. В настоящее время они представлены как два свойства:
// INotifyPropertyChanged support not shown for brevity
public DataTable GridData { get; set; }
public BindingList<ImportColumnInfo> ColumnData { get; set; }
Хитрость в работе с двумя разными наборами данных заключается в сетке. Я подклассифицировал DataGrid и дал сетке дополнительный источник данных ColumnSource в качестве свойства зависимости. Это то, что связано с ColumnData в моей модели представления. Затем я устанавливаю заголовок каждого автоматически сгенерированного столбца для соответствующим образом проиндексированных данных в источнике данных ColumnSource. Код выглядит следующим образом:
public class ImporterDataGrid : DataGrid
{
protected override void OnAutoGeneratingColumn(DataGridAutoGeneratingColumnEventArgs e)
{
base.OnAutoGeneratingColumn(e);
int columnIndex = this.Columns.Count;
var column = new ImporterDataGridColumn();
column.Header = ColumnSource[columnIndex];
column.Binding = new Binding(e.PropertyName) { Mode = BindingMode.OneWay };
e.Column = column;
}
public IList ColumnSource
{
get { return (IList)GetValue(ColumnSourceProperty); }
set { SetValue(ColumnSourceProperty, value); }
}
public static readonly DependencyProperty ColumnSourceProperty = DependencyProperty.Register("ColumnSource", typeof(IList), typeof(ImporterDataGrid), new FrameworkPropertyMetadata(null));
}
Теперь я могу выполнять обычное связывание данных в шаблонном заголовке моих столбцов, которое будет привязываться к данным в свойстве ColumnData моей модели представления.
ОБНОВЛЕНИЕ: меня попросили показать XAML для моей сетки. Это действительно просто, но вот оно:
<Controls:ImporterDataGrid
AutoGenerateColumns="True" x:Name="previewDataGrid"
VerticalScrollBarVisibility="Visible"
HorizontalScrollBarVisibility="Visible"
IsReadOnly="True"
SelectionMode="Extended"
HeadersVisibility="Column"
ItemsSource="{Binding PreviewData}"
ColumnSource="{Binding PreviewColumnData}"
Style="{StaticResource ImporterDataGridStyle}"
Background="White" CanUserReorderColumns="False" CanUserResizeRows="False"
CanUserSortColumns="False" AlternatingRowBackground="#FFFAFAFA" AllowDrop="True" />
А вот ImporterColumnHeaderStyle:
<Style x:Key="ImporterDataGridColumnHeaderStyle" TargetType="{x:Type toolkit:DataGridColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type toolkit:DataGridColumnHeader}">
<Grid>
<toolkit:DataGridHeaderBorder Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" IsClickable="{TemplateBinding CanUserSort}" IsHovered="False" IsPressed="False" SortDirection="{TemplateBinding SortDirection}">
<Grid>
<CheckBox Height="16" Margin="6,6,16,0" Name="importCheckBox" IsChecked="{Binding Path=Import}" VerticalAlignment="Top">Import Column</CheckBox>
<StackPanel IsEnabled="{Binding Path=Import}">
<ComboBox Height="24" Margin="6,29,6,0" Name="columnTypeComboBox" VerticalAlignment="Top" SelectedValue="{Binding ColumnType}" ItemsSource="{Binding Source={local:EnumList {x:Type Models:ImportColumnType}}}">
</ComboBox>
<TextBox Height="23" Margin="6,6,6,33" Name="customHeadingTextBox" VerticalAlignment="Bottom" Text="{Binding Path=CustomColumnName}" IsEnabled="{Binding ColumnType, Converter={StaticResource ColumnTypeToBooleanConverter}}" />
</StackPanel>
<TextBlock Height="20" Margin="6,0,6,7" Name="originalHeadingTextBlock" Text="{Binding Path=OriginalColumnName}" VerticalAlignment="Bottom" Foreground="Gray" />
</Grid>
</toolkit:DataGridHeaderBorder>
<Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left">
<Thumb.Style>
<Style TargetType="{x:Type Thumb}">
<Setter Property="Width" Value="8"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Cursor" Value="SizeWE"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Thumb.Style>
</Thumb>
<Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right">
<Thumb.Style>
<Style TargetType="{x:Type Thumb}">
<Setter Property="Width" Value="8"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Cursor" Value="SizeWE"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Thumb.Style>
</Thumb>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>