How to change WPF Rectangle Style Programatically
Asked Answered
T

1

8

[EDIT] *I had forgotten to include the Exception returned

'System.Windows.Style' is not a valid value for property 'Fill'*

This is my first post, I've already done lots of searching for questions where this might have already been answered to no success. I'm a complete noob when it comes to MVVM, Prism, and WPF and I have been thrown in the deep end on this one.

I wish to change the contents of 2 rectangles depending on a boolean in the Model (Binding Passed).

if a test returns Pass (bool True) then we display colour Green for first rectangle, and the second rectangle will display the UserControl.Resource Style x:Key="RectanglePass". If test fails, then first rectangle is red, and second displays UserControl.Resource Style x:Key="RectangleFail"

I have the following xaml code:

<UserControl x:Class="Integration.Memjet.Aoqc.Views.ProcessResultView"
             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="300" d:DesignWidth="300">

 <UserControl.Resources>
    <Style x:Key="RectangleFail" TargetType="Rectangle">
        <Setter Property="Fill">
            <Setter.Value>
                <VisualBrush>
                    ....
                </VisualBrush>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="RectanglePass" TargetType="Rectangle">
        <Setter Property="Fill">
            <Setter.Value>
                <VisualBrush>
                    ....
                </VisualBrush>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="60"></RowDefinition>
        <RowDefinition Height="60"></RowDefinition>
        <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>
    <Label VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="20">PASS</Label>
    <Rectangle Name="rectStatus" Grid.Row="1">
        <Rectangle.Style>
            <Style TargetType="{x:Type Rectangle}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Passed}" Value="True">
                        <Setter Property="Fill" Value="Green" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Passed}" Value="False">
                        <Setter Property="Fill" Value="Red" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Rectangle.Style>
    </Rectangle>

    <Rectangle Name="rectStatusImg" Width="120" Height="120" Grid.Row="2" >
        <Rectangle.Style>
            <Style TargetType="{x:Type Rectangle}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Passed}" Value="True">
                        <Setter Property="Fill" Value="{StaticResource RectanglePass}" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding Passed}" Value="False">
                        <Setter Property="Fill" Value="{StaticResource RectangleFail}" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Rectangle.Style>
    </Rectangle>
</Grid>
</UserControl>

The above doesn't work and returns an exception. If I was to replace the second Rectangle tag (rectStatusImg) with this line;

<Rectangle Name="rectStatusImg" Style="{StaticResource RectanglePass}" Width="120" Height="120" Grid.Row="2" ></Rectangle>

the xaml works and produces the expected result! But I wish to bind it to the Boolean Passed so I can change it programmatically.

I really hope I was able to explain my problem here.

Thank you for your help in advance, this site has always been a treasure and a great help.

Cheers, Simon

Tumult answered 19/12, 2012 at 3:31 Comment(2)
Are you setting the DataContext of the UserControl anywhere? It looks like things are set up right, including the binding, but it's not clear if you actually set up the DataContext to show the system where the values are actually coming from.Outcry
Hi @Tim, In the fileView.xaml.cs it has a fileViewModel property which returns DataContext as fileViewMode. The Interesting this is by adding DataContext to grid. It stopped producing an Exception.Tumult
R
7

define two visual brushes in your resource and create a style of rectangle with data trigger like

  <VisualBrush x:Key="FailBrush">Black</VisualBrush>
    <VisualBrush x:Key="PassBrush">Red</VisualBrush>

    <Style x:Key="ColorRectangleStyle" TargetType="Rectangle">
        <Setter Property="Fill" Value="{StaticResource FailBrush}"/>
        <Style.Triggers>
            <DataTrigger Binding="{Binding Passed}" Value="False">
                <Setter Property="Fill" Value="{StaticResource PassBrush}"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>

and use it in rectangle like

<Rectangle Name="rectStatusImg" Width="120" Height="120" Grid.Row="2" Style="{StaticResource ColorRectangleStyle}" />

Hope it helps.

Rathbun answered 19/12, 2012 at 4:3 Comment(5)
How come we only have one DataTrigger for the PassBrush? Does that mean the FailBrush will be displayed by default?Tumult
yes and you will change it into passbrush by trigger. you can change it depending on need but if you have only two colors. This should be ok.Rathbun
this is awesome. This can be my answer if i can get the Grid to be invisible (Visibility = "Hidden") then i'll show it at the end of the test, revealing a pass or a fail. I'm having issues getting this to work, <Border BorderBrush="Beige" BorderThickness="1" Height="300" Visibility="{Binding Passed, Converter={StaticResource BoolToVisiblity}}"> ...Tumult
what is the issue? also I cant see the border in your code. can u update the question with xaml?Rathbun
It works :D Thank you @D J. My Stupid mistake was that I was binding the Visibility to "Passed"! This is magic :)Tumult

© 2022 - 2024 — McMap. All rights reserved.