4
votes

How can I use a property trigger in a style (or another method) to change a property (ToolTip for example) that already has its value defined by a binding?

I have a simple button like so:

<Button Name="Button1" Style="{StaticResource ButtonStyle}" 
        ToolTip="{Binding Name}" >My Button</Button>

It has a binding on the tooltip to show the Name property of the class set as DataContext.

My problem is I want to show the Name when the button is enabled, but something else when it is disabled. I thought I could get around my problem with a style and a trigger like so:

<Style TargetType="Button" x:Key="ButtonStyle">
    <Setter Property="ToolTipService.ShowOnDisabled" Value="True" />
    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="false">
            <Setter Property="ToolTip" Value="Disabled" />
        </Trigger>
    </Style.Triggers>
</Style>

But this doesn't work. If I removed the tooltip binding from the button then I do get the correct tooltip when the button is disabled. But it seems I can't have both a binding and a trigger on the same property.

I could get around it by adding another trigger like so:

<Trigger Property="IsEnabled" Value="true">
    <Setter Property="ToolTip" Value="{Binding Name}" />
</Trigger>

But I would like to use the style for 4 or 5 buttons that will all have different bindings for the enabled ToolTip, but the same (fixed) tooltip when they are disabled.

Any suggestions?

2

2 Answers

3
votes

The easiest solution to your problem is to create a button style that all of your buttons can use (_DisabledButtonToolTipStyle in the example below) and then define a unique style for each button that applies the enabled tool tip value. If the individual buttons always have a different tool tip value then I'd recommended simply embedding the style like below; however, if you wanted to reuse the enabled tool tip style you could easily define it in your resources and give it a key.

<Window.Resources>
    <Style x:Key="_DisabledButtonToolTipStyle" TargetType="Button">
        <Setter Property="ToolTipService.ShowOnDisabled" Value="True" />
        <Style.Triggers>
            <Trigger Property="IsEnabled" Value="false">
                <Setter Property="ToolTip" Value="Disabled" />
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

<Grid>
    <Button Name="Button1" Content="My Button">
        <Button.Style>
            <Style TargetType="Button" BasedOn="{StaticResource _DisabledButtonToolTipStyle}">
                <Setter Property="ToolTip" Value="{Binding Name}" />
            </Style>
        </Button.Style>
    </Button>
</Grid>
2
votes

Your problem has nothing to do with binding, the problem is that properties you set directly on the element override the properties set in a style, for example:

Given the style

<Style TargetType="Button">
    <Setter Property="Background" Value="Blue"/>
</Style>

And those two buttons:

<Button Content="1st"/>
<Button Content="2nd" Background="Red"/>

The first button will get its background from the style but the second overrides the style background.

You can get what you want with triggers but not using styles, you can use a DataTemplate like this (the TextBox and CheckBox are there for testing):

<ContentPresenter Content="{Binding}">
    <ContentPresenter.ContentTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBox Name="edt" Text="Tooltip text"/>
                <Button Name="btn" Content="x" 
                    ToolTip="{Binding ElementName=edt, Path=Text}" 
                    ToolTipService.ShowOnDisabled="True"/>
                <CheckBox Content="Enabled" 
                    IsChecked="{Binding ElementName=btn, Path=IsEnabled}"/>
            </StackPanel>
            <DataTemplate.Triggers>
                <Trigger SourceName="btn" Property="IsEnabled" Value="False">
                    <Setter TargetName="btn" Property="ToolTip" Value="Disabled"/>
                </Trigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </ContentPresenter.ContentTemplate>
</ContentPresenter>