如何在DataGrid列标题上设置DataContext

7
在我的 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>

我想要将标题的数据上下文设置为一个“header”对象(其中包含在DataTemplate中引用的“Name”和“Data”属性)。不幸的是,我无法像其他地方建议的那样使用StackPanel_Loaded事件,因为当用户开始列拖放操作时也会调用事件处理程序。
正确的设置DataGrid列标题DataContext的方法是什么?
3个回答

7

以下是如何在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>

我尝试过这种方法,它几乎可以工作。但是当我绑定两个列标题名称时,每一列都会得到第一列的名称。我已经仔细检查了我的数据绑定属性,据我所知,没有任何愚蠢的错误。你有什么想法是什么原因导致这种情况吗? - Dave
你是救命恩人。非常感谢,这在 .Net 4.5 WPF 应用程序上完美运行。 - Rukshan Dangalla

6
原来可以使用类型为对象的 Header 属性作为 DataTemplate 的 DataContext(如上所示):
Style headerStyle = (Style)Resources["ColumnHeaderStyle"];
DataGridTextColumn col = new DataGridTextColumn();
col.HeaderStyle = headerStyle;
col.Header = myHeaderDataContext; // DataContext for ColumnHeaderStyle
dataGrid.Columns.Add(col);

虽然我没有采用完全相同的方法,但是你解释Header属性是DataContext的做法值得点赞。 - Gavin Osborn

3

基于Matt的回答,我想到了一个解决方案,即将标题绑定在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这样的顶层元素的数据上下文。

感谢您提供的好解决方案!我以此为基础编写了我的解决方案,并且遵守了所有版权规定 :)。 - Anatoliy Nikolaev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接