Frage

In my Window I have a series of six buttons that indicate the six possible states for one of the properties of my ViewModel. The one that's active needs to be highlighted. To do this, I've created the following ControlTemplate for the buttons:

<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>

The template is then used like so:

<Button Grid.Column="0" Template="{StaticResource SnijRichtingTemplate}"
        HorizontalAlignment="Right" Click="SnijRichting_Click"
        Tag="{StaticResource XLinks}" />

Where the tag is just an instance defined in the XAML:

<wg:SnijRichting x:Key="XLinks" SnijAs="X" Negatief="True" />

The MultibindingConverter is nothing fancy:

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();
    }
}

Basically, each button has a Tag with the new value. In the click handler, the ViewModel's property is set to the button's Tag. The button state is updated by checking whether the button's Tag is equal to the ViewModel property.

The problem is that this doesn't work. When the EqualityToBooleanConverter is executed, the second value is null. By removing the Path="Tag" bit from the second binding I see that the TemplatedParent is a ContentPresenter rather than the Button I was expecting, which explains why Tag is null. Now of course I could write a ValueConverter to get the correct value using VisualTreeHelper.GetParent to get the ContentPresenter's parent (which returns the desired Button), but surely there must be a way to do this from XAML? The obvious Path="Parent.Tag" doesn't work, since the Parent of the ContentPresenter is apparently a Border.

Does anyone know how to access the button's Tag property from XAML?

War es hilfreich?

Lösung

Found the problem. Turns out you need {RelativeSource Mode=Self}, not {RelativeSource TemplatedParent}.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top