I have been going crazy with binding a combobox to an enum typed property of a class, where the enum itself is declared in that same class.
I am trying to follow the answer provided here (wpf combobox binding to enum what i did wrong?) Specifically I am using the suggested MarkupExtension code and the matching xaml code.
My working code is:
Defining the Enum in a separate file.
namespace EnumTest
{
public enum TestEnum {one, two, three, four };
}
Class that uses the Enum (Note that the propertyChanged code has been removed to simplify things):
namespace EnumTest
{
public class Test : INotifyPropertyChanged
{
private TestEnum _MyVar;
public TestEnum MyVar {
get { return _MyVar; }
set
{
_MyVar = value;
OnPropertyChanged("MyVar");
}
}
public Test()
{
_MyVar = TestEnum.three;
}
}
}
Program file that uses the class:
namespace EnumTest
{
public partial class Window1 : Window
{
Test _oTest = new Test();
public Window1()
{
InitializeComponent();
cmbBox.DataContext = _oTest;
}
}
}
Extension method for displaying the Enum
namespace EnumTest
{
[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);
}
}
}
And the xaml code that is used to display the data:
<Window x:Class="EnumTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:w="clr-namespace:EnumTest"
Title="Window1" Height="300" Width="300">
<Grid>
<ComboBox Name="cmbBox"
Height="20"
Width="80"
ItemsSource="{Binding Source={w:EnumValues EnumType=w:TestEnum}}"
SelectedItem="{Binding Path=MyVar}"
/>
</Grid>
</Window>
The above is all good and dandy, but I want to define the Enum within the Test class and ditch the Enum from being defined at the global scope. Like so:
namespace EnumTest
{
public class Test : INotifyPropertyChanged
{
// Declare Enum **INSIDE** the class
public enum TestEnum {one, two, three, four };
private TestEnum _MyVar;
public TestEnum MyVar {
get { return _MyVar; }
set
{
_MyVar = value;
OnPropertyChanged("MyVar");
}
}
public Test()
{
_MyVar = TestEnum.three;
}
}
}
The SO question I referred to alludes to the matching xaml syntax as being:
<ComboBox Name="cmbBox"
...
ItemsSource="{Binding Source={w:EnumValues EnumType=w:Test+TestEnum}}"
...
/>
But this (sort of) does not work for me. When I do a clean build I get a "Build succeeded" message on the VS 2008 status bar, but I also get an error being reported in the xaml
Type 'Test+TestEnum' was not found.
But the code runs as expected!
However this means that the xaml designer will not load. So I am sort of screwed in doing any more wpf work until I can clear the xaml error.
I am now wondering if this is a VS 2008 SP1 issue, and not a problem on my part.
Edit
Notes The SO question that I got the MarkupExtension code from uses this style of syntax for the xaml:
<ComboBox ItemsSource="{w:EnumValues w:TestEnum}"/>
When I use that I get a compilation error saying that no EnumValues constructor takes 1 parameter. I did some googling and this seems to be an error in VS. I Am using VS 2008 SP1. I did see some comments that alluded to it being in the VS 2010 beta. Anyway, that is why I use the xaml syntax of
<ComboBox ItemsSource="{w:EnumValues EnumType=w:TestEnum}"/>
As this syntax works!
Another way of getting the enum values for use as a data source:
<Window.Resources>
<ObjectDataProvider
MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="TestValues">
<ObjectDataProvider.MethodParameters>
<w:Type2
TypeName="w:Test+TestEnum" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
...
ItemsSource="{Binding Source={StaticResource TestValues}}"
Note that you still need the Type2Extension
because of weirdness with TypeExtension
and nested types. But you wouldn't need the extra custom markup extension. This way is better if you'll be using the list in multiple places, as you can declare it in your App.xaml
resources.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With