绑定组合框嵌套在一个类的枚举(Binding a ComboBox to an enum neste

2019-06-27 14:24发布

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

我试图按照这里提供的答案(WPF组合框结合枚举我做错了什么?)具体我使用的是建议的MarkupExtension代码和匹配的XAML代码。

我的工作代码为:

定义枚举在一个单独的文件。

namespace EnumTest
{
    public enum TestEnum {one, two, three, four };
}

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

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

使用该类的程序文件:

namespace EnumTest
{
    public partial class Window1 : Window
    {
        Test _oTest = new Test();

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

用于显示所述枚举扩展方法

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

并且,用于显示的数据的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="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>

以上是所有良好和花花公子,但我想定义测试类的枚举和在全球范围内被定义沟枚举。 像这样:

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

所述SO质疑我称为暗指匹配XAML语法之中:

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

但是,这(样的)不会为我工作。 当我做一个干净的构建,我得到一个“构建成功”的消息在VS 2008状态栏上,但我也得到一个错误在XAML中被报告

Type 'Test+TestEnum' was not found.  

但代码运行正常!

然而,这意味着,XAML设计将不会加载。 所以,我有点拧在做任何更多的WPF工作,直到我可以清除XAML错误。

我现在想,如果这是一个VS 2008 SP1的问题,不是我的一个问题。

编辑

  1. 使我的问题的陈述更加明确。
  2. 试图乔尔的第一个解决方案,但我最终的代码运行和 2个XAML错误
  3. 试图Joel的第二个解决办法,制定开箱的 - 所以我有一个去!

备注 SO问题,我得到的MarkupExtension代码使用语法的XAML的这种风格:

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

当我使用,我得到一个编译错误,说没有EnumValues构造函数接受1个参数。 我做了一些谷歌搜索,这似乎是在VS.错误 我使用VS 2008 SP1。 我也看到一些评论说,提到它在VS 2010 Beta版之中。 不管怎么说,这就是为什么我用的XAML语法

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

由于这句法的作品!

Answer 1:

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

<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的资源。



Answer 2:

怎么样使用x:Type标记扩展?

{w:EnumValues EnumType={x:Type w:Test+TestEnum}}

除了实现INotifyPropertyChanged ,我精确复制你的代码。 我得到的是你得到的错误,但它似乎运行得很好。 这是非常恼人的不能够加载设计,虽然。 没什么我已经试过已经解决了这个问题。

我没有找到这个页面在MSDN上关于嵌套类型,并在该线程的建议是一个自定义MarkupExtension解决嵌套类的名称。 我试图得到它的工作,但至今没有运气。 我上得到类似的错误Type2Extension有时,我也得到“枚举类型未设置”与其他调整。

啊哈! 有没有在原作者是如何调用错误GetType() 这里的修正Type2Extension和我是如何使用它:

public class Type2Extension : System.Windows.Markup.TypeExtension {
    public Type2Extension() {
    }

    public Type2Extension( string typeName ) {
        base.TypeName = typeName;
    }

    public override object ProvideValue( IServiceProvider serviceProvider ) {
        IXamlTypeResolver typeResolver = (IXamlTypeResolver) serviceProvider.GetService( typeof( IXamlTypeResolver ) );
        int sepindex = TypeName.IndexOf( '+' );
        if ( sepindex < 0 )
            return typeResolver.Resolve( TypeName );
        else {
            Type outerType = typeResolver.Resolve( TypeName.Substring( 0, sepindex ) );
            return outerType.Assembly.GetType( outerType.FullName + "+" + TypeName.Substring( sepindex + 1 ) );
        }
    }
}

和XAML:

ItemsSource="{Binding Source={w:EnumValues {w:Type2 w:Test+TestEnum}}}"

这似乎是做工精细的设计负荷。 我会添加Type2Extension到我自己的小图书馆。

编辑:奇怪的是,如果我改变了在EnumValues

if ( this.EnumType == null )
    throw new ArgumentException( "The enum type is not set" );

为此:

if ( this.EnumType == null )
    return null;

然后,这些构造错误消失。 这是我改变了一两件事。 不过,我很快要发布获得枚举值的另一种方式。



文章来源: Binding a ComboBox to an enum nested in a class