将ComboBox绑定到嵌套在类中的枚举 [英] Binding a ComboBox to an enum nested in a class

查看:183
本文介绍了将ComboBox绑定到嵌套在类中的枚举的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经疯狂地将一个组合框绑定到一个类的枚举类型的属性,其中枚举本身被声明在同一个类中。



我正在尝试按照这里提供的答案具体来说,我正在使用建议的MarkupExtension代码和匹配的xaml代码。



我的工作代码是:



在单独的文件中定义枚举。

 命名空间EnumTest 
{
public enum TestEnum {one,two,three,four};
}

使用枚举的类(请注意,propertyChanged代码已被删除以简化东西):

 命名空间EnumTest 
{
public class Test:INotifyPropertyChanged
{
private TestEnum _MyVar;
public TestEnum MyVar {
get {return _MyVar; }
set
{
_MyVar = value;
OnPropertyChanged(MyVar);
}
}

public Test()
{
_MyVar = TestEnum.Three;
}
}
}

使用课程的程序文件:

 命名空间EnumTest 
{
public partial class Window1:Window
{
Test _oTest = new Test();

public Window1()
{
InitializeComponent();
cmbBox.DataContext = _oTest;
}
}
}

显示枚举的扩展方法

 命名空间EnumTest 
{
[MarkupExtensionReturnType(typeof(object []))]
public class EnumValuesExtension:MarkupExtension
{
public EnumValuesExtension()
{
}

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

[ConstructorArgument(enumType)]
public Type EnumType {get;组;

public override object ProvideValue(IServiceProvider serviceProvider)
{
if(this.EnumType == null)
throw new ArgumentException(枚举类型未设置);
return Enum.GetValues(this.EnumType);
}
}
}

而且xaml代码是用于显示数据:

 < 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 =Window1Height =300Width =300>
< Grid>
< ComboBox Name =cmbBox
Height =20
Width =80
ItemsSource ={Binding Source = {w:EnumValues EnumType = w:TestEnum }}
SelectedItem ={Binding Path = MyVar}
/>
< / Grid>
< / Window>

以上都是好的,但是我想定义Enum 强>测试类,并将枚举从全局范围定义。像这样:

 命名空间EnumTest 
{
public class Test:INotifyPropertyChanged
{
//声明枚举** INSIDE **类
public枚举TestEnum {一,二,三,四};
private TestEnum _MyVar;
public TestEnum MyVar {
get {return _MyVar; }
set
{
_MyVar = value;
OnPropertyChanged(MyVar);
}
}

public Test()
{
_MyVar = TestEnum.Three;
}
}
}

我提到的SO问题暗示匹配的xaml语法为:

 < ComboBox Name =cmbBox
...
ItemsSource ={Binding Source = {w:EnumValues EnumType = w:Test + TestEnum}}
...
/>

但是(这种)对我来说不起作用。当我做一个干净的构建,我在VS 2008状态栏上得到一个建立成功消息,但是我也收到一个错误报告在xaml

 未找到Test + TestEnum类型。 

但代码按预期运行



但是这意味着xaml设计器将不会加载。所以我在做任何更多的wpf工作,直到我可以清除xaml错误有点困扰。



我现在想知道这是否是VS 2008 SP1问题,而不是



修改



  1. 尝试了Joel的第一个解决方案,但是最后我的代码是运行 2 xaml错误

  2. 尝试Joel的第二个解决方案,直接开箱即用,所以我要去那个!






注意
我获得MarkupExtension代码的SO问题使用xaml的这种语法风格:

 < ComboBox ItemsSource ={w:EnumValues w:TestEnum}/> 

当我使用它时,我收到一个编译错误,表示没有EnumValues构造函数需要1个参数。我做了一些谷歌搜索,这似乎是VS中的一个错误。我使用VS 2008 SP1。我确实看到一些意见,提到它在VS 2010测试版。无论如何,这就是为什么我使用xml语法

 < ComboBox ItemsSource ={w:EnumValues EnumType = w:TestEnum }/> 

由于此语法正常工作!

解决方案

获取枚举值用作数据源的另一种方法:

 < 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}}

请注意,您仍然需要 Type2Extension ,因为奇怪的是 TypeExtension 和嵌套类型。但是您不需要额外的自定义标记扩展名。如果您在多个地方使用该列表,那么这种方式会更好,因为您可以在 App.xaml 资源中声明这一点。


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

  1. Made my problem statement more explicit.
  2. Tried Joel's 1st solution, but I ended up with the code running and 2 xaml errors
  3. Tried Joel's 2nd solution and that worked straight out of the box - so I am going with that one!


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.

这篇关于将ComboBox绑定到嵌套在类中的枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆