从 XAML 中的 ControlTemplate 访问按钮的 Tag 属性

Fal*_*nNL 0 wpf xaml binding parent controltemplate

在我的窗口中,我有一系列六个按钮,它们指示我的 ViewModel 属性之一的六种可能状态。需要突出显示处于活动状态的那个。为此,我为按钮创建了以下 ControlTemplate:

<ControlTemplate x:Key="SnijRichtingTemplate" TargetType="Button">
    <Border Name="toggleButton" BorderThickness="1" BorderBrush="{StaticResource KleurRadioCheckOuter}" Background="Transparent" Width="20" Height="20" Cursor="Hand">
        <TextBlock Name="text" Foreground="{StaticResource KleurRadioCheckOuter}"
                   Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Tag}"
                   ToolTip="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Tag.ToolTip}"
                   HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Border>

    <ControlTemplate.Triggers>
        <DataTrigger Value="True">
            <DataTrigger.Binding>
                <MultiBinding Converter="{StaticResource EqualityToBooleanConverter}">
                    <Binding Path="SnijRichting" />
                    <Binding Path="Tag" RelativeSource="{RelativeSource TemplatedParent}" />
                </MultiBinding>
            </DataTrigger.Binding>
            <Setter TargetName="toggleButton" Property="BorderBrush" Value="{StaticResource KleurTekstDonker}" />
            <Setter TargetName="text" Property="Foreground" Value="{StaticResource KleurTekstDonker}" />
        </DataTrigger>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter TargetName="toggleButton" Property="BorderBrush" Value="{StaticResource Kleur2}" />
            <Setter TargetName="text" Property="Foreground" Value="{StaticResource Kleur2}" />
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>
Run Code Online (Sandbox Code Playgroud)

然后使用该模板,如下所示:

<Button Grid.Column="0" Template="{StaticResource SnijRichtingTemplate}"
        HorizontalAlignment="Right" Click="SnijRichting_Click"
        Tag="{StaticResource XLinks}" />
Run Code Online (Sandbox Code Playgroud)

其中标记只是 XAML 中定义的实例:

<wg:SnijRichting x:Key="XLinks" SnijAs="X" Negatief="True" />
Run Code Online (Sandbox Code Playgroud)

MultibindingConverter 没什么特别的:

public class EqualityToBooleanConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return values[0] == values[1];
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上,每个按钮都有一个带有新值的标签。在单击处理程序中,ViewModel 的属性设置为按钮的 Tag。通过检查按钮的 Tag 是否等于 ViewModel 属性来更新按钮状态。

问题是这行不通。当执行 EqualityToBooleanConverter 时,第二个值为 null。通过从第二个绑定中删除 Path="Tag" 位,我发现 TemplatedParent 是一个 ContentPresenter,而不是我期望的 Button,这解释了为什么 Tag 为 null。现在,我当然可以编写一个 ValueConverter 来使用 VisualTreeHelper.GetParent 获取正确的值,以获取 ContentPresenter 的父级(返回所需的 Button),但肯定有一种方法可以从 XAML 执行此操作?明显的 Path="Parent.Tag" 不起作用,因为 ContentPresenter 的父级显然是一个边框。

有谁知道如何从 XAML 访问按钮的 Tag 属性?

Fal*_*nNL 5

发现问题了。事实证明,您需要 {RelativeSource Mode=Self},而不是 {RelativeSource TemplatedParent}。