如何使用xaml从DataGridColumnHeader获取DatagridTextColumn的名称

时间:2012-11-14 04:59:35

标签: wpf

我为DataGrid的DataGridTextColumn定义了以下xaml代码。

<DataGridTextColumn x:Name="UserIdColumn" Binding="{Binding Path=UserId}" HeaderStyle="{StaticResource DataGridHeaderStyle}"/>

这是DataGridTextColumn的HeaderStyle

<Style x:Key="DataGridHeaderStyle" TargetType="{x:Type DataGridColumnHeader}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="DataGridColumnHeader">
                <StackPanel>
                    <TextBlock x:Name="ColumnName" Text="UserId" />
                    <TextBox x:Name="UserIdFilter" Width="100">
                        <i:Interaction.Triggers>
                            <i:EventTrigger EventName="TextChanged">
                                <cal:ActionMessage MethodName="UserIdFilterChanged">
                                    <cal:Parameter Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridTextColumn}}, Path=Name}"/>
                                    <cal:Parameter Value="{Binding ElementName=UserIdFilter, Path=Text}" />
                                </cal:ActionMessage>
                            </i:EventTrigger>
                        </i:Interaction.Triggers>
                    </TextBox>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>    

正如我可以看到的那样,我正试图使用​​这行代码访问DataGridColumnHeader的ControlTemplate中的DataGridTextColumn的 Name 属性

<cal:Parameter Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridTextColumn}}, Path=Name}"/>

以上行返回null,为什么?

有没有其他方法可以从DataGridColumnHeader的控件模板中获取DataGridTextColumn的 Name 属性?

1 个答案:

答案 0 :(得分:2)

您正在恢复空值,原因有两个: 第一个是DataGridTextColumn不是可视化树的一部分,并且不是数据网格的可视实例。这只是一个描述数据网格列应该如何显示的实例。因此,DataGridTextColumn不是您单元格的祖先的一部分。 我看到恢复DataGridTextColumn的唯一方法是以某种方式继续:

<TextBox x:Name="UserIdFilter" Width="100" Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}, Path=Columns[0]}">

这样,您应该使用DataGridTextColumn的实例设置Textbox的Tag属性(您可以使用snoop检查它是否正常工作)

然后,解释为什么你有一个空值的第二个原因是DataGridTextColumn没有Name属性。 您可以做的只是创建一个像这样的附加属性:

public class XamlHelper
{
    public static readonly DependencyProperty NameProperty = DependencyProperty.RegisterAttached("Name", typeof(string), typeof(XamlHelper));

    public static string GetName(DependencyObject obj)
    {
        return (string)obj.GetValue(NameProperty);
    }

    public static void SetName(DependencyObject obj, string value)
    {
        obj.SetValue(NameProperty, value);
    }
}

...用这一个替换列定义的名称:

<DataGridTextColumn alias:XamlHelper.Name="UserIdColumn" Binding="{Binding Path=UserId}" HeaderStyle="{StaticResource DataGridHeaderStyle}"/>

以这种方式检索属性:

<Style x:Key="DataGridHeaderStyle" TargetType="{x:Type DataGridColumnHeader}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="DataGridColumnHeader">
                <StackPanel>
                    <TextBlock x:Name="ColumnName" Text="UserId" />
                    <TextBox x:Name="UserIdFilter" Width="100"  Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}, Path=Columns[0]}">
                        <i:Interaction.Triggers>
                            <i:EventTrigger EventName="TextChanged">
                                <cal:ActionMessage MethodName="UserIdFilterChanged">
                                    <cal:Parameter Value="{Binding ElementName=UserIdFilter, Path=Tag.(alias:XamlHelper.Name)}"/>
                                    <cal:Parameter Value="{Binding ElementName=UserIdFilter, Path=Text}" />
                                </cal:ActionMessage>
                            </i:EventTrigger>
                        </i:Interaction.Triggers>
                    </TextBox>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>   

...希望我在这段代码中没有犯过太多错误,但我觉得这样的事情应该有效

请注意,我使用了文本框的tag属性有一个缓冲区,因为我注意到绑定的findAncestor模式能够正确恢复数据网格(我对可视树没有的元素有一些问题)。也许在你的参数中有一个独特的绑定也可以...

标签也非常适合进行测试,因为它允许在snoop中看到值!

如果某些要点不明确,请不要犹豫

修改 我检查了DataGridCOlumnHeaderClass,我发现了似乎包含你所期望的属性...... 因此,应该可以这样做:

<Style x:Key="DataGridHeaderStyle" TargetType="{x:Type DataGridColumnHeader}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="DataGridColumnHeader">
                <StackPanel>
                    <TextBlock x:Name="ColumnName" Text="UserId" />
                    <TextBox x:Name="UserIdFilter" Width="100"  Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridColumnHeader}}, Path=Column}">
                        <i:Interaction.Triggers>
                            <i:EventTrigger EventName="TextChanged">
                                <cal:ActionMessage MethodName="UserIdFilterChanged">
                                    <cal:Parameter Value="{Binding ElementName=UserIdFilter, Path=Tag.(alias:XamlHelper.Name)}"/>
                                    <cal:Parameter Value="{Binding ElementName=UserIdFilter, Path=Text}" />
                                </cal:ActionMessage>
                            </i:EventTrigger>
                        </i:Interaction.Triggers>
                    </TextBox>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>