How can I use enum types in XAML?

54,897

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.

Share:
54,897
davymartu
Author by

davymartu

Updated on July 12, 2022

Comments

  • davymartu
    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
    davymartu over 11 years
    Thanks for reply! If my "NodeType" is in another Namespace, how can i import in xaml?
  • Rachel
    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 namespace MyNamespace from the assembly MyAssembly to the XAML file, and it can be referenced by the prefix "local": xmlns:local="clr-namespace:MyAssembley.MyNamespace;assembly=‌​MyAssembly"
  • davymartu
    davymartu over 11 years
    I'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
    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 called XHelper
  • davymartu
    davymartu over 11 years
    I've tried but there is an error: Nested Type are not supported!
  • Rachel
    Rachel over 11 years
    @user1696549 Hrrrmmm I think I recall seeing somewhere that x:Static only supported two levels, so local:Class.Property works, but local:Class.Property.SubProperty does not. Try using {x:Type local:XHelper.NodeType.Type_DB} for your ConverterParameter instead
  • tpartee
    tpartee almost 9 years
    This 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
    Rachel almost 9 years
    Yes 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
    tpartee almost 9 years
    I 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
    Rachel almost 9 years
    Its 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
    tpartee almost 9 years
    Try 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
    Rachel almost 9 years
    Ahhh 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
    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
    tpartee almost 9 years
    I 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. ;)