Ste
Ste

Reputation: 187

WPF RelativeSource not updating it's value

I'm trying to implement a button that uses XAML-defined icons to show a different state (like in the second comment here: https://codereview.stackexchange.com/questions/183871/wpf-button-with-xaml-defined-icon-that-changes-with-state). The icons are defined with a "Fill" property that uses a RelativeSource binding, like so:

<Canvas x:Key="icon_stop"
        x:Shared="False"
        Width="76" 
        Height="76" 
        Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
    <Rectangle 
        Width="28.5" 
        Height="28.5" 
        Canvas.Left="23.75" 
        Canvas.Top="23.75" 
        Stretch="Fill"
        Fill="{Binding RelativeSource={
            RelativeSource Mode=FindAncestor,
            AncestorType=Control
        }, Path=Foreground}"
    />
</Canvas>

The button is bound to a property in the window's ViewModel like this:

<Button Name="PlayStopButton"
              Padding="20 0 20 0" 
              Command="{Binding Path=StartStopCommand}">
    <ContentControl Style="{StaticResource style_icon}">
        <Binding 
            Path="IsRunning"
            UpdateSourceTrigger="PropertyChanged"
            FallbackValue="{StaticResource icon_play}">
            <Binding.Converter>
                <converters:BoolToObjectConverter
                    TrueObject="{StaticResource icon_stop}"
                    FalseObject="{StaticResource icon_play}"
                    NullObject="{StaticResource icon_play}"
                />
            </Binding.Converter>
        </Binding>
    </ContentControl>
</Button>

(I'm omitting the "style" part here and the "BoolToObjectConverter", that should be clear for the purpose)

The problem is that, when I run the program, the button gets correctly updated, but the icon is not visible. This is because the "icon_stop" resource is not updated with the correct "Fill" color. In fact, if I force it (for example to "Black") the icon shows correctly.

It seems to me that the "RelativeSource" bounded property gets not updated. I think this is related to the fact that the resource is a "StaticResource" and thus gets created only once on the application loading.

I've found that there are also "DynamicResource" references in WPF, but I can't use them here (or at least I can't see how now as them must be bound to a dependency property and I have the value converter here).

How can I solve this?

Upvotes: 0

Views: 384

Answers (1)

Clemens
Clemens

Reputation: 128060

Your XAML seems overly complicated. You may try something simple like this:

<Style TargetType="Button" x:Key="PlayButtonStyle">
    <Setter Property="ContentTemplate">
        <Setter.Value>
            <DataTemplate>
                <Path Fill="{Binding Foreground,
                                     RelativeSource={RelativeSource AncestorType=Button}}"
                      Data="{Binding}"/>
            </DataTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="Content" Value="M5,0 L25,15 5,30Z"/>
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsRunning}" Value="True">
            <Setter Property="Content">
                <Setter.Value>
                    <RectangleGeometry Rect="0,0,30,30"/>
                </Setter.Value>
            </Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>

Try it like this:

<Button Style="{StaticResource PlayButtonStyle}" Foreground="Red" />

Upvotes: 1

Related Questions