How can I use enum types in XAML?
Solution 1
I had a similar question here, and my end result was to create a generic IValueConverter that passed the enum
value I wanted to match in as the ConverterParameter
, and it returns true
or false
depending on if the bound value matches the (int)
value of the Enum.
The end result looks like this:
XAML Code:
<DataTrigger Value="True"
Binding="{Binding SomeIntValue,
Converter={StaticResource IsIntEqualEnumConverter},
ConverterParameter={x:Static local:NodeType.Type_DB}}">
Converter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (parameter == null || value == null) return false;
if (parameter.GetType().IsEnum && value is int)
{
return (int)parameter == (int)value;
}
return false;
}
Solution 2
You just need to make sure that your namespace is accounted-for in your XAML header then you can reference both custom DPs and enum values directly in your markup.
For example I use this code to do just that:
<DataTemplate.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}" Value="True" />
<Condition Binding="{Binding Type}" Value="{x:Static loc:AppProfileItemType.Custom}" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter TargetName="PART_Delete" Property="Visibility" Value="{x:Static Visibility.Visible}" />
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</DataTemplate.Triggers>
Note that you can't access DataTriggers in a Style, you need to instead make a DataTemplate or ControlTemplate for that (however, .NET 4 adds the ability to set triggers in styles). You can override the ControlTemplate from a Style like so:
<Style x:Key="MyCustomButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ContentPresenter />
<ControlTemplate.Triggers>
<!-- Put your DataTriggers here -->
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
For DataTemplates you want to have bindings to an object, you can simply use a ContentPresenter and set its content to the object you want to display along with a DataTemplate definition to use for display of the object. There's always a way to use DataTriggers it's just not always direct or as simple as using a Style.
Solution 3
There's no need to make life so complicated. Enum is easily convertible to string, so you can use that string value in tirgger.
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<DataTrigger Binding="{Binding Type}" Value="Type_DB">
<Setter Property="Source" Value="/Images/DB.PNG"/>
</DataTrigger>
<DataTrigger Binding="{Binding Type}" Value="Type_SERVER">
<Setter Property="Source" Value="/Images/SERVER.PNG"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
But if you store an int value in your enum... because you can assign:
NodeType val = (NodeType)619;
then... Yes... you have to use a converter.
davymartu
Updated on July 12, 2022Comments
-
davymartu almost 2 years
I'm learning WPF and I encountered the following problem:
I have an enum type in another namespace than my XAML:
public enum NodeType { Type_SYSTEM = 1, // System Type_DB = 2, // Database Type_ROOT = 512, // Root folder Type_FOLDER = 1024, // Folder }
in my XAML I'd like to trigger an image with an integer
<Image.Style> <Style TargetType="{x:Type Image}"> <Style.Triggers> <DataTrigger Binding="{Binding Type}" Value="{NodeType: }"> <Setter Property="Source" Value="/Images/DB.PNG"/> </DataTrigger> <DataTrigger Binding="{Binding Type}" Value="128"> <Setter Property="Source" Value="/Images/SERVER.PNG"/> </DataTrigger> </Style.Triggers> </Style> </Image.Style>
Is there a way to get an integer value and compare it with an enum type directly in XAML code?
My enum is in namespace
AnotherNamespace.Types
<DataTrigger Binding="{Binding IntegerType}" Value="MyEnumType.Type_DB"> <Setter Property="Source" Value="/Images/SERVER.PNG"/> </DataTrigger>
-
davymartu over 11 yearsThanks for reply! If my "NodeType" is in another Namespace, how can i import in xaml?
-
Rachel over 11 years@user1696549 You can add other namespaces to your XAML using
xmlns
in the root tag. For example, this line will add the namespaceMyNamespace
from the assemblyMyAssembly
to the XAML file, and it can be referenced by the prefix"local"
:xmlns:local="clr-namespace:MyAssembley.MyNamespace;assembly=MyAssembly"
-
davymartu over 11 yearsI've imported namespace succesfully, but xaml tell me that "NodeType" doesn't exist in the namespace...my namespace is "XFramework.domain.helpers" and my enum is into XHelper class in the same namespace.
-
Rachel over 11 years@user1696549 You'll probably need to use something like
local:XHelper.NodeType.Type_DB
if your enum is in a class calledXHelper
-
davymartu over 11 yearsI've tried but there is an error: Nested Type are not supported!
-
Rachel over 11 years@user1696549 Hrrrmmm I think I recall seeing somewhere that
x:Static
only supported two levels, solocal:Class.Property
works, butlocal:Class.Property.SubProperty
does not. Try using{x:Type local:XHelper.NodeType.Type_DB}
for yourConverterParameter
instead -
tpartee almost 9 yearsThis seems like an overly complex solution for a simple problem. You can do a direct comparison from within XAML without need for any custom converters or markup extensions. See my answer below.
-
Rachel almost 9 yearsYes you can compare an Enum to an Enum in XAML like you display here, but this question is about comparing an Enum to an Integer, which you cannot do as far as I know without a converter or custom behavior. Also, yes you can put Triggers in a Style as the OP demonstrated in the example code of the question :)
-
tpartee almost 9 yearsI don't have the reputation to edit the question title, but I'd argue that the title is misleading: "How can i use enum types in XAML?" says nothing about integers and integer comparison, the title would be more clear being "How can I compare enum to integer in XAML?" Also, you cannot put DataTrigger in a Style element, normal Triggers cannot test bindings.
-
Rachel almost 9 yearsIts important to read the whole question, not the title. I don't really want to make the change since it's an old question and it would bump it to the top, but if this were a newer question I would. :) Also, perhaps I'm misunderstanding what you're saying, but I am fairly posititive you can put DataTriggers in a Style.Triggers. I do it all the time.
-
tpartee almost 9 yearsTry adding a DataTrigger to your Style.Triggers collection sometime. Both the Visual Studio IDE and the compiler will throw errors letting you know that DataTrigger is not an allowed child in a Style.Triggers collection. DataTriggers are intentionally only permitted in places where a DataContext is guaranteed to be present: in a DataTemplate or a ControlTemplate. Edit: Apparently I missed that this was changed in .Net 4.0 and Visual Studio 2013. My bad!
-
Rachel almost 9 yearsAhhh I see, I didn't realize that. I figured it had to be something like a version difference or a misunderstanding, since you seemed so convinced it was the case :)
-
phonetagger almost 9 years@tpartee: Would you mind adding the C# side of the equation above? I'm having trouble figuring out how to tie a C# class member variable that's an instance of an enum, into my XAML code, specifically to trigger a group of setters to change the characteristics of a DataGridCell inside a Style inside a DataGrid definition. I'm also new to both C# and WPF (and XAML of course), and everyone's answer always leaves out key details (usually on the C# side) assuming their readers can fill in the blanks. If you have the time, could you answer my question?... stackoverflow.com/q/31615946/1245420
-
tpartee almost 9 yearsI added an answer to your question as you asked, I think that should solve your current issue, but I also noticed you said you don't know anything about templates. I would strongly, strongly suggest that you invest some time in learning how to do templating in WPF/XAML as it's seriously one of the most powerful features it has and any well-designed application will make the most use of templates as it can. FWIW - Templating isn't the solution to your current issue, though. ;)