datatrigger on enum to change image

C#Wpf

C# Problem Overview


I've got a button with a fixed background image and would like to show a small overlay image on top of it. Which overlay image to chose depends on a dependency property (LapCounterPingStatus) of the according viewmodel.

This is what I got so far:

<Button>
	<Grid>
		<Image Stretch="None"> <!-- Background Image -->
			<Image.Style>
				<Style TargetType="{x:Type Image}">
					<Setter Property="Source" Value="/Images/Pingn.png"/>
				</Style>
			</Image.Style>
		</Image>
		<Image Stretch="None" Panel.ZIndex="1"> <!-- Small Overlay Image -->
			<Image.Style>
				<Style TargetType="{x:Type Image}">
					<Style.Triggers>
						<DataTrigger Binding="{Binding Path=LapCounterPingStatus}" Value="PingStatus.PING_UNKNOWN">
							<Setter Property="Source" Value="/Images/RefreshOverlayn.png"/>
						</DataTrigger>
						<DataTrigger Binding="{Binding Path=LapCounterPingStatus}" Value="PingStatus.PING_FAILURE">
							<Setter Property="Source" Value="/Images/ErrorOverlayn.png"/>
						</DataTrigger>
						<DataTrigger Binding="{Binding Path=LapCounterPingStatus}" Value="PingStatus.PING_SUCCESS">
							<Setter Property="Source" Value="/Images/CheckmarkOverlayn.png"/>
						</DataTrigger>
					</Style.Triggers>
				</Style>
			</Image.Style>
		</Image>
	</Grid>
</Button>

Relevant parts of my viewmodel

public class ConfigurationViewModel
{
    public enum PingStatus { PING_UNKNOWN, PING_SUCCESS, PING_FAILURE };

    public PingStatus LapCounterPingStatus
    {
	    get { return _lapCounterPingStatus; }
	    set
	    {
	        _lapCounterPingStatus = value;
	        RaisePropertyChanged(LapCounterPingStatusPropertyName);
	    }
    }
}

Right now, no overlay image at all is displayed. What could be wrong?


UPDATE

Trace window of my IDE is showing System.ArgumentException and System.FormatException. Could the problem source be a unknown type of enumeration PingStatus im the XAML?

C# Solutions


Solution 1 - C#

You need 2 things to get this working:

1 - Add an xmlns reference in the root element of your XAML file, to the namespace where your Enum is defined:

<UserControl ...
xmlns:my="clr-namespace:YourEnumNamespace;assembly=YourAssembly"> 

2 - in the Value property of the DataTrigger, use the {x:Static} form:

 <DataTrigger Binding="{Binding Path=LapCounterPingStatus}" Value="{x:Static my:PingStatus.PING_UNKNOWN}">

Notice that the Enum type must be prefixed with the xmlns prefix you defined above.

Edit:

If your Enum is declared inside a class you need to use the syntax:

{x:Static namespace:ClassName+EnumName.EnumValue}

for example:

{x:Static my:ConfigurationViewModel+PingStatus.PING_UNKNOWN}

Solution 2 - C#

Complete worked example for WPF + MVVM.

Tested on MSVC 2017.

In the view:

<TextBlock Text="Some text to be colored by an enum">
    <TextBlock.Style>
        <Style TargetType="{x:Type TextBlock}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding StatusIcon}" Value="{x:Static my:StatusIcon.Warning}">
                    <Setter Property="Foreground" Value="Yellow"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding StatusIcon}" Value="{x:Static my:StatusIcon.Error}">
                    <Setter Property="Foreground" Value="Red}"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TextBlock.Style>
</TextBlock>

If using ReSharper, and if the DataContext is set up properly, there will be intellisense when you hit the . after StatusIcon, i.e. it will show the properties of the enum which are Debug, Info, Warning or Error.

If using ReSharper, it will suggest the following update to the namespace in the header for the XAML file(its good like that):

xmlns:my="clr-namespace:Class.Path.MyViewModel;assembly=MyAssembly"

And the VieModel:

public enum StatusIcon
{
    Debug,
    Info,
    Warning,
    Error
}

public class MyViewModel
{
    public StatusIcon StatusIcon { get; }
}

We also use Fody for automated binding.

Solution 3 - C#

You can simply set enum value as DataTrigger Value... Tested on MSVC 2017.

<TextBlock Text="Some text to be colored by an enum">
	<TextBlock.Style>
		<Style TargetType="{x:Type TextBlock}">
			<Style.Triggers>
				<DataTrigger Binding="{Binding StatusIcon}" Value="Warning">
					<Setter Property="Foreground" Value="Yellow"/>
				</DataTrigger>
				<DataTrigger Binding="{Binding StatusIcon}" Value="Error">
					<Setter Property="Foreground" Value="Red}"/>
				</DataTrigger>
			</Style.Triggers>
		</Style>
	</TextBlock.Style>
</TextBlock>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnabulkeView Question on Stackoverflow
Solution 1 - C#Federico BerasateguiView Answer on Stackoverflow
Solution 2 - C#ContangoView Answer on Stackoverflow
Solution 3 - C#Adam SilenkoView Answer on Stackoverflow