Binding to Self in Style with DataTrigger
Asked Answered
L

1

5

I have a Style for a Button. Depending on if the Button is enabled or not, I want to change the Background. This is what it looks like:

<Style x:Key="MyButtonStyle" TargetType="Button">
    <Style.Triggers>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Button}, Path=IsEnabled, PresentationTraceSources.TraceLevel=High}" Value="False">
            <Setter Property="Background" Value="Purple"/>
        </DataTrigger>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Button}, Path=IsEnabled, PresentationTraceSources.TraceLevel=High}" Value="True">
            <Setter Property="Background" Value="Yellow"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

This is just a basic example. Actually I need a MultiDataTrigger, but it's not even working with a regular DataTrigger. All I see is a gray button.

This is the trace:

System.Windows.Data Warning: 56 : Created BindingExpression (hash=31767240) for Binding (hash=6303779)
System.Windows.Data Warning: 58 : Path: 'IsEnabled'
System.Windows.Data Warning: 60 : BindingExpression (hash=31767240): Default mode resolved to OneWay
System.Windows.Data Warning: 61 : BindingExpression (hash=31767240): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 62 : BindingExpression (hash=31767240): Attach to System.Windows.Controls.Button.NoTarget (hash=24311680)
System.Windows.Data Warning: 66 : BindingExpression (hash=31767240): RelativeSource (FindAncestor) requires tree context
System.Windows.Data Warning: 65 : BindingExpression (hash=31767240): Resolve source deferred
System.Windows.Data Warning: 67 : BindingExpression (hash=31767240): Resolving source
System.Windows.Data Warning: 70 : BindingExpression (hash=31767240): Found data context element: (OK)
System.Windows.Data Warning: 73 : Lookup ancestor of type Button: queried Grid (hash=35377238)
System.Windows.Data Warning: 73 : Lookup ancestor of type Button: queried ContentPresenter (hash=51189900)
System.Windows.Data Warning: 73 : Lookup ancestor of type Button: queried Border (hash=48541090)
System.Windows.Data Warning: 73 : Lookup ancestor of type Button: queried StartStopControl (hash=22721178)
System.Windows.Data Warning: 73 : Lookup ancestor of type Button: queried Grid (hash=32321338)
System.Windows.Data Warning: 73 : Lookup ancestor of type Button: queried ContentPresenter (hash=31184590)
System.Windows.Data Warning: 73 : Lookup ancestor of type Button: queried Border (hash=37117888)
System.Windows.Data Warning: 73 : Lookup ancestor of type Button: queried MenuPanelControl (hash=873549)
System.Windows.Data Warning: 73 : Lookup ancestor of type Button: queried Grid (hash=29953511)
System.Windows.Data Warning: 73 : Lookup ancestor of type Button: queried ContentPresenter (hash=42576376)
System.Windows.Data Warning: 73 : Lookup ancestor of type Button: queried AdornerDecorator (hash=66649760)
System.Windows.Data Warning: 73 : Lookup ancestor of type Button: queried Border (hash=23566381)
System.Windows.Data Warning: 73 : Lookup ancestor of type Button: queried MainWindow (hash=38392424)

It looks like it goes through the whole visual tree, starting with the Grid where the Button is placed in. Why does it not start with the Button?

Latisha answered 15/9, 2016 at 10:35 Comment(1)
If my answer had helped you, please, mark the check box as "answer" if you don't mind.Epiphragm
E
15

Why don't you change it to Trigger?

  <Style x:Key="MyButtonStyle"
           TargetType="Button">
        <Style.Triggers>
            <Trigger Property="IsEnabled"
                     Value="False">
                <Setter Property="Background"
                        Value="Purple" />
            </Trigger>
            <Trigger Property="IsEnabled"
                     Value="True">
                <Setter Property="Background"
                        Value="Yellow" />
            </Trigger>
        </Style.Triggers>
    </Style>

Or if you want to use it anyway, you don't need to find an ancestor, because you're currently on the button:

  <Style x:Key="MyButtonStyle"
           TargetType="Button">
        <Style.Triggers>
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled, PresentationTraceSources.TraceLevel=High}"
                         Value="False">
                <Setter Property="Background"
                        Value="Purple" />
            </DataTrigger>
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled, PresentationTraceSources.TraceLevel=High}"
                         Value="True">
                <Setter Property="Background"
                        Value="Yellow" />
            </DataTrigger>
        </Style.Triggers>
    </Style>

If it doesn't help you, you should give more details: Original XAML code and maybe your View Model's code too.

Epiphragm answered 15/9, 2016 at 11:5 Comment(4)
I need to use DataTrigger becuase I also want to access properties from my ViewModel. When I try your second example, Intellisense gives me an error, however it seems I can compile and run it just fine. I'll have a look if I can reconstruct the error. Thanks so far.Latisha
It works, but somehow Intellisense shows it as an error. I guess I can live with that.Latisha
@Epiphragm your suggestion to use Trigger instead of DataTrigger worked for me. But any idea why? ThanksSatyriasis
The second example worked for a TopBar button controlTemplate. <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=Content}" Value="1" /> <Condition Binding="{Binding RelativeSource={RelativeSource AncestorType=views:BaseWindow, Mode=FindAncestor}, Path=WindowState}" Value="Normal" /> </MultiDataTrigger.Conditions> <MultiDataTrigger.Setters> <Setter TargetName="ContentPresenter" Property="Content" Value="2" /> </MultiDataTrigger.Setters> </MultiDataTrigger>Bluh

© 2022 - 2024 — McMap. All rights reserved.