Search code examples
c#wpfdata-bindingdatatrigger

WPF Databinding DataTrigger to change color of shape based on boolean value


I am trying to change the color of a shape by means of databinding and data trigger.

But i am still new to WPF and all.

Let me illustrate with an example. this is a group box

<GroupBox x:Class="Server.Host.SingleAxisControls"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:host="clr-namespace:Server.Host"
         mc:Ignorable="d" 
         d:DesignWidth="200">
    <Grid>
        <StackPanel Orientation="Vertical" Width="180" >
            <host:MyRectangleControl x:Name="MyRectangle" />
            <Button Click="OnButton_Click" Width="80" Margin="20,5,20,5">On</Button>
            <Button Click="OffButton_Click" Width="80">Off</Button>
        </StackPanel>
    </Grid>
</GroupBox>

MyRectangleControl is a usercontrol of something like

<UserControl x:Class="Server.Host.MyRectangleControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="30" d:DesignWidth="30">
<Grid>
    <Rectangle  HorizontalAlignment="Center"
              Height="25"
              Margin="0,0,0,0"
              Stroke="Black"
              VerticalAlignment="Center"
              Width="25" 
              Fill="red">
        <Rectangle.Style>
            <Style TargetType="Rectangle">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=Test,UpdateSourceTrigger=PropertyChanged}"
                                 Value="True">
                        <Setter Property="Fill"
                                Value="Green" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Rectangle.Style>
    </Rectangle>
</Grid>

In the code behind the groupbox, I have something like

namespace Server.Host
{
public partial class SingleAxisControls : INotifyPropertyChanged
{
    public SingleAxisControls()
    {
        InitializeComponent();

        MyRectangle.DataContext = this;
    }

    private bool _test;
    public bool Test
    {
        get { return _test; }
        set
        {
            _test = value;
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("Test"));
            }
        }
    }

    private void OnButton_Click(object sender, RoutedEventArgs e)
    {
        Test = true;
    }

    private void OffButton_Click(object sender, RoutedEventArgs e)
    {
        Test = false;
    }
}

I am not sure what is wrong but it doesn't seem change the color of the rectangle when i change the value of test from false to true.


Solution

  • This is a problem of value precedence.

    When you set a DependencyProperty directly in the declaration of an Element this value has higher precedence than a value set in a style.

    All you have to do is set the Fill property to Red in the Style:

    <Rectangle  HorizontalAlignment="Center"
              Height="25"
              Margin="0,0,0,0"
              Stroke="Black"
              VerticalAlignment="Center"
              Width="25" 
              >
        <Rectangle.Style>
            <Style TargetType="Rectangle">
                <Setter Property="Fill" Value="Red"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=Test,UpdateSourceTrigger=PropertyChanged}"
                                 Value="True">
                        <Setter Property="Fill"
                                Value="Green" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Rectangle.Style>
    </Rectangle>