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:
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??