14

I have searched around and it seems very easy to bind enums to combobox, just retrieve Enum values as a list of strings via an ObjectDataProvider from the static Enum.GetValues method, however i can't get it to work. The error is Type ContactExportType was not found.

I have an enum called ContactExportType, it resides on Enums class. This class is part of the CEM.Marketing.Objects namespace.

This is what i have:

<UserControl 
 xmlns:local="clr-namespace:CEM.Marketing.Objects"
 xmlns:sys="clr-namespace:System;assembly=mscorlib">

<Grid>
<Grid.Resources>
        <ObjectDataProvider MethodName="GetValues"
                    ObjectType="{x:Type sys:Enum}"
                    x:Key="ContactExportTypes">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="local:ContactExportType" />
        </ObjectDataProvider.MethodParameters>

    </ObjectDataProvider>
    </Grid.Resources>

</Grid>
 <ComboBox 
        ItemsSource="{Binding {StaticResource ContactExportTypes}}"
...

Thanks, Angela

H.B.
  • 166,899
  • 29
  • 327
  • 400
Angela
  • 531
  • 2
  • 8
  • 18
  • 1
    Thanks Chris for your help. I couldn't do it in XAML after trying different things. Seems like it does not support one level down in the class structure. What I did to make it work is to bind the itemSource in code behind. combobox.ItemsSource = Enum.GetValues(typeof (Enums.ContactExportType)); – Angela May 18 '09 at 16:32

2 Answers2

37

To access a nested type, you should use the "+" separator :

<ObjectDataProvider MethodName="GetValues"
                    ObjectType="{x:Type sys:Enum}"
                    x:Key="ContactExportTypes">
    <ObjectDataProvider.MethodParameters>
        <x:Type TypeName="local:Enums+ContactExportType" />
    </ObjectDataProvider.MethodParameters>

</ObjectDataProvider>

By the way, there is a simpler way to bind to the values of an enum, without using an ObjectDataProvider. It's based on a custom markup extension :

<ComboBox ItemsSource="{local:EnumValues local:Enums+ContactExportType}"/>

Here is the code for the EnumValues markup extension :

[MarkupExtensionReturnType(typeof(object[]))]
public class EnumValuesExtension : MarkupExtension
{
    public EnumValuesExtension()
    {
    }

    public EnumValuesExtension(Type enumType)
    {
        this.EnumType = enumType;
    }

    [ConstructorArgument("enumType")]
    public Type EnumType { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (this.EnumType == null)
            throw new ArgumentException("The enum type is not set");
        return Enum.GetValues(this.EnumType);
    }
}
Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • How do you do this if your enum is not local? – gonzobrains Oct 06 '15 at 14:54
  • @gonzobrains, what do you mean "not local" ? In the example above, `local` is just an XML namespace prefix mapped to the CLR namespace where the enum is defined. You can use any prefix and map it to any CLR namespace. – Thomas Levesque Oct 06 '15 at 15:02
1
<ObjectDataProvider MethodName="GetValues"
                    ObjectType="{x:Type local:Enums}"
                    x:Key="ContactExportTypes">

should be

<ObjectDataProvider MethodName="GetValues"
                    ObjectType="{x:Type sys:Enum}"
                    x:Key="ContactExportTypes">

and

<x:Type TypeName="local:ContactExportType" /> 

should be

<x:Type TypeName="CEM.Marketing.Objects.ContactExportType"/>

the sys:Enum points to the Enum framework class the typename in the parameter points to your fully qualified type-name.

check Bea Stollnitz's blog

    <ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type sys:Enum}" x:Key="odp">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="namespace.class.TShirtSizes"/>
            </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>

<ComboBox ItemsSource="{Binding Source={StaticResource odp}}" IsSynchronizedWithCurrentItem="true"/>
Muad'Dib
  • 28,542
  • 5
  • 55
  • 68