Markup Extension in Data Trigger

2019-06-23 18:40发布

问题:

To translate my WPF application I use a Markup extension which returns a Binding object. This allows me to switch the language while the application is running. I use this Markup like this:

<TextBlock Text="{t:Translate 'My String'}" />"

I would like to change a Buttons text through a data Trigger:

<Button>
    <Button.Style>
        <Style TargetType="{x:Type Button}">
            <Setter Property="Template">
                <Setter.Value>
                    <!-- Custom control template, note the TextBlock formating -->
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Grid x:Name="ContentHolder">
                            <ContentPresenter TextBlock.Foreground="Red" TextBlock.FontWeight="Bold" />
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <!-- Custom text triggered by Data Binding... -->
            <Style.Triggers>
                <DataTrigger Binding="{Binding MessageRowButton}" Value="Retry">
                    <Setter Property="Button.Content" Value="{t:Translate Test}" />
                </DataTrigger>
                <DataTrigger Binding="{Binding MessageRowButton}" Value="Acknowledge">
                    <Setter Property="Button.Content" Value="{t:Translate Test}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

This leads to the following exception:

A 'Binding' cannot be set on the 'Value' property of type 'Setter'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.

Ok, this make sense to me. I tried to define TextBlock in my Resource and use {StaticResource MyResource} in the DataTrigger's Setter Value. But when I do this, the style of my Button is not correctly applied...

How can I work with my markup extension and change text on the button without destring the ability to style the string inside the button?

回答1:

Try returning the markup extension itself (this) if the target (IProvideValueTarget.TargetObject) is a setter. It will be reevaluated when the style is applied to an actual element.

public object ProvideValue(IServiceProvider serviceProvider)
{
    var pvt = service.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
    if (pvt.TargetObject is Setter)
        return this;

    ...
}