Databinding an Enum in WPF...

The situation I have is this - I have a class defined as such:

  public class MyClass
  {
     public int TheInt { get; set; }
     public string TheString { get; set; }
     public MyEnum TheEnum { get; set; }
  }

with 'MyEnum' defined as:

public enum MyEnum   
{
      A, B, C, D   
} 

I have a Window that displays the data in such a way:

  <Window.Resources>
    <CollectionViewSource x:Key="SortedEnumView">
      <CollectionViewSource.SortDescriptions>
        <ComponentModel:SortDescription/>
      </CollectionViewSource.SortDescriptions>
      <CollectionViewSource.Source>
        <ObjectDataProvider MethodName="GetNames" ObjectType="{x:Type System:Enum}">
          <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="TheEnum"/>
          </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
      </CollectionViewSource.Source>
    </CollectionViewSource>
  </Window.Resources>
  <StackPanel>
    <TextBox x:Name="txtTheInt" Text="{Binding Path=TheInt}"/>
    <TextBox x:Name="txtTheString" Text="{Binding Path=TheString}"/>
    <ComboBox x:Name="cboTheEnum" DataContext="{StaticResource SortedEnumView}" ItemsSource="{Binding}"/>
  </StackPanel>

In my C# code, I read a 'MyClass' instance from my data layer:

   myClass = Data.GetClass("XX");

and assign it to the DataContext of the Window:

   DataContext = myClass;

Soooo... At this stage, if I run the window, change the contents of the two text boxes the change is reflected back to the member field, which is what I want to happen. Obviously, if I change the cboTheEnum selection, this won't be reflected as I haven't bound it to the 'MyClass' instance.

To get the value I end up doing:

   myClass.TheEnum = (TheEnum) Enum.Parse(typeof(TheEnum), _cboTheEnum.SelectedItem.ToString(), true);

Ok, so how about binding directly to the 'TheEnum' property?

   <ComboBox x:Name="cboTheEnum" ItemsSource="{Binding Path=TheEnum}"/>

Ahhh no. I don't get anything now! At least previously there was something to select!
Hmmm, ok, so we're setting the DataContext in the code as well as the XAML. Let's get rid of the ComboBox's DataContext:

   <ComboBox x:Name="cboTheEnum" ItemsSource="{Binding Source={StaticResource SortedEnumView}}"/>

Ok, F5...

Good, looking the same as before, still not updating the object though...
Let's try binding the SelectedValue to the 'TheEnum' property...

   <ComboBox x:Name="cboTheEnum" ItemsSource="{Binding Source={StaticResource SortedEnumView}}" SelectedValue="{Binding Path=TheEnum}"/>

Da DA!! - Da Dunt.
Nope, still no joy...

Do we need a converter of some variety?? Certainly seems so...
Let's write a converter...

  public class MyEnumToStringConverter : IValueConverter
  {
     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
     {
         return value.ToString();
     }
 
     public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
     {
         return (MyEnum) Enum.Parse( typeof ( MyEnum ), value.ToString(), true );
     }
  }

That's all well and good, but what about the using of said converter?
We need to add a key to the resources of the Window...

  <Window.Resources>
    <Converters:MyEnumToStringConverter x:Key="MyEnumConverter"/>
  </Window.Resources>

Ok, now that's defined, let's add it to the ComboBox:

   <ComboBox x:Name="cboTheEnum" ItemsSource="{Binding Source={StaticResource SortedEnumView}}" SelectedValue="{Binding Path=TheEnum, Converter={StaticResource MyEnumConverter}}"/>

Right, let's fire up this bad boy...

Huzzah!
We have a winner...
Now we can change the 'TheEnum' property via the ComboBox, or indeed via code: myClass.TheEnum = MyEnum.B; for example, and this is displayed correctly in the ComboBox and the property on the myClass instance is correct as well!

Having done all this.. is this even correct??
Is there a better *simpler* way to achieve the same goal??

Print | posted @ Thursday, October 16, 2008 1:39 PM

Comments on this entry:

Gravatar # re: Databinding an Enum in WPF...
by anon at 11/3/2008 8:41 PM

Thanks, This was very helpful.
Gravatar # re: Databinding an Enum in WPF...
by Sally at 12/30/2008 10:37 AM

I have a Enum for example...

public enum TypeIdentifier {
NotSet = 0,
Type1= 1,
Type2= 2,
Type3= 3,
Type4= 4,
Type5= 5
}

public class CommonObject
{

TypeIdentifier myTypeIdentifier {get; set;}
}

I have a WPF UserControl that has a generalized object binding.I have a common object that is used three times,masked as 5 different UserControls (member use varies).

I need to include hidden the value say TypeIdentifier.Type1 in UserControl (TextBOX?) One.How can I do this.I just need the object member to be set to TypeIdentifier.Type1 what ever control in the UserControl it is.The thing is that I can't directly reference the enum above in my user control project.

Gravatar # re: Databinding an Enum in WPF...
by Chris at 12/30/2008 10:53 AM

Hi Sally,

I'm not really sure exactly what you're asking, is it that you want to store the value of the enum in a control, but you want that value to be hidden from the display?

If you want to email me at my xclave address (top of the page in the 'news' section) then we can see if we can sort it out!

Cheers

Chris
Gravatar # re: Databinding an Enum in WPF...
by Shimmy at 3/26/2009 3:52 AM

love u!
thanks, that was indeed helpful, I used this converter it's more applicapble for me, I want it to be dynamic for all the enums in my project:

<ValueConversion(GetType([Enum]), GetType(String))> _
Public Class EnumConverter : Implements IValueConverter
Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
targetType = Type.GetType("<MyNamespace>." & parameter)
Return [Enum].Parse(targetType, value, True).ToString
End Function
Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
targetType = Type.GetType("<MyNamespace>." & parameter)
Return Int32.Parse([Enum].Parse(targetType, value, True))
End Function
End Class

Change <MyNamespace> to your namespace name.

XAML:

<Window.Resources>
<converters:EnumConverter x:Key="EnumConverter"/>

<CollectionViewSource x:Key="PhoneType">
<CollectionViewSource.Source>
<ObjectDataProvider ObjectType="{x:Type sys:Enum}" MethodName="GetNames">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="src:PhoneType"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</CollectionViewSource.Source>
</CollectionViewSource>
</Window.Resources>


Thanks you chris for the info and ideas!!!!!!!!!

<ComboBox ItemsSource="{Binding Source={StaticResource PhoneType}}" SelectedValue="{Binding Path=PhoneType, Mode=TwoWay, Converter={StaticResource EnumConverter}, ConverterParameter=PhoneType}"/>

Thank you
Gravatar # re: Databinding an Enum in WPF...
by Chris at 3/26/2009 9:21 AM

Heh,

I'm glad it helped. I had a look at your code, and it's good to get the dependency on a specific Enum removed. I had a little play and converted my code to be Enum agnostic:

public class EnumToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value.ToString();
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return Enum.Parse(targetType, value.ToString(), true);
}
}

One of the things I noticed was that you use the 'ConverterParameter' to pass in the type, but you don't need to as the 'targetType' argument is the type. So you can still use the original XAML:

<ComboBox ItemsSource="{Binding Source={StaticResource SortedEnumView}}"
SelectedValue="{Binding Path=TheEnum, Converter={StaticResource EnumConverter}}"/>

without the argument.

Cheers

Chris
Gravatar # re: Databinding an Enum in WPF...
by Alan at 10/1/2009 11:23 AM

Thanks for the good example in displaying the Enum. But how do I pass the VALUE of Enum as a parameter in WPF ObjectDataProvider:

Example:

public enum Continental
{
Asia,
Europ,
NorthAmerica,
Africa
}

public class CountryDataSvc
{
public static IList GetCountriesInContinental(Continental)
{
//Retrieve the countries based on continental
IList countries = ... ...
return countries;
}
}


public class CountryViewModel
{
public IList GetCoutriesInAsia()
{
IList countriesInAsia = CountryDataSvc.GetCountriesInContinental(Continental.Asia);
return countriesInAsia;
}
}



Gravatar # re: Databinding an Enum in WPF...
by melfid at 8/18/2010 11:13 AM

For some reason your solution didn't work for me (with combobox)?!
However, I was able to get it working by binding to the SelectedIndex property instead.
Post A Comment
Title:
Name:
Email:
Comment:
Verification: