WPF Style DataTrigger with binding to DataContext not working
Asked Answered
R

1

20

I have a TextBox with a style that has a DataTrigger which changes the text, like this:

<Grid>
    <TextBlock Text="Foo">
        <TextBlock.Style>
            <Style BasedOn="{StaticResource TextStyle}" TargetType="TextBlock">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding MyBool}" Value="True">
                        <Setter Property="Text" Value="Bar"/>
                    </DataTrigger>
                 </Style.Triggers>
             </Style>
         </TextBlock.Style>
     </TextBlock>
</Grid>

But it's not working, the text never changes to "Bar". I have tested using another TextBlock with Text="{Binding MyBool}" and this text changes from "False" to "True". Snoop reveals no errors that I can see and there is nothing in the output.

This question may seem like a duplicate of WPF Trigger binding to MVVM property, but my code does not seem different from the accepted answer there (http://www.thejoyofcode.com/Help_Why_cant_I_use_DataTriggers_with_controls_in_WPF.aspx, section "Using a style") in any relevant way. And using a DataTemplate as suggested in the actual answer seems wrong since I only want this to apply to a single TextBlock, but if it is correct, I'm not sure how to write a DataTemplate for this...

EDIT:

This is what the property I'm binding to looks like:

public bool MyBool
{
    get { return _myBool; }
    set
    {
        if (_myBool== value)
            return;

        _myBool= value;
        NotifyPropertyChanged();
    }
}
private bool _myBool;
Rena answered 11/10, 2013 at 13:20 Comment(3)
First thing you need to do is turn up debug messages for databinding: i.sstatic.net/MF8i5.png Next, re-run and check the output window and see what errors are there. You may have done this; the fact that you mentioned snoop indicates you're far ahead of the pack. Probably need the relevant parts of the VM in the question, as well.Kinsley
I'd check your output window for errors. It may be something as simple as the binding being messed up.Kloof
Yes, as I mentioned: "there is nothing in the output". Warnings for binding errors are enabled. I'll update the main post with the property... but as I also mentioned, I can bind to and display the value of the same property just fine, it just doesn't work in the trigger.Rena
L
63

Dependency Properties can be set from many different places; inline, animations, coercion, triggers, etc. As such a Dependency Property Value Precedence list was created and this dictates which changes override which other changes. Because of this order of precedence, we can't use a Trigger to update a property that is explicitly set inline in your XAML. Try this instead:

<Grid>
    <TextBlock>
        <TextBlock.Style>
            <Style BasedOn="{StaticResource TextStyle}" TargetType="TextBlock">
                <!-- define your default value here -->
                <Setter Property="Text" Value="Foo" />
                <Style.Triggers>
                    <DataTrigger Binding="{Binding MyBool}" Value="True">
                        <!-- define your triggered value here -->
                        <Setter Property="Text" Value="Bar" />
                    </DataTrigger>
                 </Style.Triggers>
             </Style>
         </TextBlock.Style>
     </TextBlock>
</Grid>
Lakesha answered 11/10, 2013 at 13:30 Comment(5)
Now THAT is just silly... is there actually a good reason for this?Rena
I would disagree with you there... it's all about the Dependency Property Value Precedence as there are many ways to set a DependencyProperty. It just makes more sense if you are aware of it.Lakesha
That's so weird.. I remember many times that I explicitly set a property in Xaml and then added a Trigger and it worked. Check this out: https://mcmap.net/q/661832/-concatenated-text-in-textblock-datatrigger For now I'm enjoying your solution - It works for me so +1 for solution (explanation need source!)Eby
I updated my answer to make my point clearer. Setting a property inline will stop it from being changed by a Trigger. Setting it as above in my answer is the correct way to set an initial value for a property when using a Trigger. I hope that is clearer now.Lakesha
In this code, when MyBool is set to false, Text will become Foo again right? In other words, there's no need to specify another DataTrigger for the False case?Pinchpenny

© 2022 - 2024 — McMap. All rights reserved.