0

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プロパティを取得する他の方法はありますか?

4

1 に答える 1

2

2つの異なる理由でnull値を回復しています。1つ目は、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で正しく機能することを確認できます)

次に、null値がある理由を説明する2番目の理由は、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>   

...このコードであまりミスをしなかったといいのですが、そのようなものはうまくいくはずだと思います

バインディングのfindAncestorモードでデータグリッドを適切に回復できると確信しているため、テキストボックスのtagプロパティにバッファーがあることに注意してください(ビジュアルツリーではない要素でいくつかの問題が発生しました)。たぶん、あなたのパラメータにユニークなバインディングを持っていることも機能します...

タグは、スヌープで値を確認できるため、テストを行うのにも最適です。

いくつかの点が明確でない場合は躊躇しないでください

編集: 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>   
于 2012-11-14T10:01:43.643 に答える