Как установить DataContext в заголовке столбца DataGrid

В моем пользовательском элементе управления Silverlight 3 я показываю базовый элемент управления DataGrid. Мне нужно сгенерировать столбцы программно следующим образом:

Style headerStyle = (Style)Resources["ColumnHeaderStyle"];
DataGridTextColumn col = new DataGridTextColumn();
col.HeaderStyle = headerStyle;
dataGrid.Columns.Add(col);

Стиль определяется следующим образом:

<Style x:Name="ColumnStyle" x:Key="ColumnHeaderStyle" 
       TargetType="prim:DataGridColumnHeader">
    <Setter Property="ContentTemplate">
        <Setter.Value>
            <DataTemplate>
                <StackPanel Loaded="StackPanel_Loaded">
                    <TextBlock Text="{Binding Name}" />
                    <TextBlock Text="{Binding Data}" />
                </StackPanel>
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

Я хочу установить контекст данных заголовка для объекта "заголовок" (со свойствами "Имя" и "Данные", на которые есть ссылки в шаблоне данных). К сожалению, я не могу использовать событие StackPanel_Loaded, как предлагается в другом месте, потому что обработчик событий также вызывается, когда пользователь запускает операцию перетаскивания столбца.

Как правильно установить DataContext заголовка столбца DataGrid?

3 ответа

Решение

Оказывается, что можно использовать свойство Header (которое имеет тип Object) в качестве DataContext для DataTemplate (установленного, как показано выше):

Style headerStyle = (Style)Resources["ColumnHeaderStyle"];
DataGridTextColumn col = new DataGridTextColumn();
col.HeaderStyle = headerStyle;
col.Header = myHeaderDataContext; // DataContext for ColumnHeaderStyle
dataGrid.Columns.Add(col);

Вот как вы это сделаете в XAML (это работает в WPF; не уверен, работает ли он в SL)

<DataGridTextColumn Binding="{Binding Path=Discount}">
    <DataGridTextColumn.HeaderStyle>
        <Style TargetType="DataGridColumnHeader">
            <Setter Property="Content" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=DataContext.DiscountHeader}" />
        </Style>
    </DataGridTextColumn.HeaderStyle>
</DataGridTextColumn>

Основываясь на ответе Мэтта, я нашел решение связать заголовок на DataGridCellsPanel который в Snoop, похоже, имеет правильный контекст данных:

  <DataGridTemplateColumn.HeaderStyle>
     <Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource CenterAlignedColumnHeaderStyle}">
         <Setter Property="Content" Value="{Binding Path=DataContext.Location, RelativeSource={RelativeSource AncestorType={x:Type DataGridCellsPanel}}}" />
      </Style>
  </DataGridTemplateColumn.HeaderStyle>

И это не навязчиво в том смысле, что вы все еще можете наследовать от заголовков с пользовательским стилем (см. Пример выше) или события стиля заголовка базового столбца:

 <DataGridTemplateColumn.HeaderStyle>
     <Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
     <Setter Property="Content" Value="{Binding Path=DataContext.Location, RelativeSource={RelativeSource AncestorType={x:Type DataGridCellsPanel}}}" />
     </Style>
 </DataGridTemplateColumn.HeaderStyle>

Преимущество этого решения состоит в том, что он является чистым и чистым XAML и ссылается на ближайшего предка, содержащего правильный текст данных, вместо того, чтобы пытаться получить доступ к тексту данных элементов верхней иерархии, таких как UserControl.

Другие вопросы по тегам