Wpf 将组合框绑定到类中嵌套的枚举
我一直在疯狂地将组合框绑定到类的枚举类型属性,其中枚举本身在同一个类中声明 我试图遵循这里提供的答案,特别是我使用建议的MarkupExtension代码和匹配的xaml代码 我的工作代码是: 在单独的文件中定义枚举Wpf 将组合框绑定到类中嵌套的枚举,wpf,class,combobox,enums,nested,Wpf,Class,Combobox,Enums,Nested,我一直在疯狂地将组合框绑定到类的枚举类型属性,其中枚举本身在同一个类中声明 我试图遵循这里提供的答案,特别是我使用建议的MarkupExtension代码和匹配的xaml代码 我的工作代码是: 在单独的文件中定义枚举 namespace EnumTest { public enum TestEnum {one, two, three, four }; } 使用枚举的类(请注意,已删除propertyChanged代码以简化操作): 使用类的程序文件: namespace EnumTes
namespace EnumTest
{
public enum TestEnum {one, two, three, four };
}
使用枚举的类(请注意,已删除propertyChanged代码以简化操作):
使用类的程序文件:
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>
我提到的这个问题暗指匹配的xaml语法是:
<ComboBox Name="cmbBox"
...
ItemsSource="{Binding Source={w:EnumValues EnumType=w:Test+TestEnum}}"
...
/>
但是代码按预期运行
但是,这意味着xaml设计器将不会加载。因此,在我清除xaml错误之前,我几乎是在做更多的wpf工作
我现在想知道这是否是VS2008SP1的问题,而不是我的问题
编辑
注释 我从中获得MarkupExtension代码的问题对xaml使用了这种语法:
<ComboBox ItemsSource="{w:EnumValues w:TestEnum}"/>
当我使用它时,我得到一个编译错误,表示没有EnumValues构造函数接受1个参数。我在谷歌上搜索了一下,这似乎是VS中的一个错误。我正在使用VS2008SP1。我确实看到一些评论,暗示它是在VS2010测试版。无论如何,这就是为什么我使用
<ComboBox ItemsSource="{w:EnumValues EnumType=w:TestEnum}"/>
因为这个语法有效 使用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 ) );
}
}
}
这似乎可以正常工作,并且设计器可以加载。我将把Type2Extension
添加到我自己的小库中
编辑:奇怪的是,如果我在EnumValues
中更改此选项:
if ( this.EnumType == null )
throw new ArgumentException( "The enum type is not set" );
为此:
if ( this.EnumType == null )
return null;
然后这些构造函数错误就消失了。这是我改变的另一件事。但是,我很快将发布另一种获取枚举值的方法。另一种获取用作数据源的枚举值的方法:
<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}}"
...
ItemsSource=“{Binding Source={StaticResource TestValues}}”
请注意,您仍然需要
Type2Extension
,因为TypeExtension
和嵌套类型很奇怪。但是您不需要额外的自定义标记扩展。如果您将在多个位置使用该列表,这种方法会更好,因为您可以在App.xaml
resources中声明它。如果您的意思是:ItemsSource=“{Binding Source={w:EnumValues EnumType={x:Type w:Test+TestEnum}”,那么这只会导致一个大的编译失败。回答之后,我开始将示例代码放在一起重新创建(只是为了看看它是否有效)。如果我发现了什么,我会编辑的。谢谢你。我现在太累了,懒得去操心,但我明天一早就去看看。我是wpf的新手,为了完成基本的工作,我不得不跳过这些障碍,这让我非常恼火。@Joel-我已经实现了Ty2Extension类并使用了我们的xaml,但它并没有让我走得更远。事实上,现在我在xaml中有更多的错误“类型“Tye2extension”的无构造函数有1个参数”和“类型“EnumValuesExtension”的无构造函数有1个参数”。但代码按预期运行并找到枚举。一个真正的WTF@Joel-看到它对您有效,我现在想知道我的VS2008 SP1安装是否有问题?顺便说一句,我只让你的xaml使用w:Test+testemr根据构造函数的错误,它只发生在设计器中。否则它应该可以正常工作。要避免此错误,请在单独的assembly@Thomas:我已经忘记了设计师在何时何地生成什么类型以及如何实例化它们时是如何变得脾气暴躁的。@Joel-和新手wpf程序员是如何知道这类事情的?为了满足构建工具的一部分,知道将一个类放在一个单独的程序集中是相当模糊的。但我会继续努力,直到我得到合理的理解。再次感谢。@Thomas-谢谢你的提示。这根本不是我会考虑的事情——即使在谷歌搜索了那个特定的问题之后。@Peter:是的,它是模糊的。不过,它对我来说并不经常出现。我正试图找到一个链接来解释苹果酒是如何实例化事物的,因为我所能记得的只是一些关于基类的东西。非常感谢你——它已经让我发疯太久了!非常好-我在MethodParameters中声明枚举时缺少“+”,这让我发疯。
ItemsSource="{Binding Source={w:EnumValues {w:Type2 w:Test+TestEnum}}}"
if ( this.EnumType == null )
throw new ArgumentException( "The enum type is not set" );
if ( this.EnumType == null )
return null;
<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}}"