以下面的代码为例:

public enum ExampleEnum { FooBar, BarFoo }

public class ExampleClass : INotifyPropertyChanged
{
    private ExampleEnum example;

    public ExampleEnum ExampleProperty 
    { get { return example; } { /* set and notify */; } }
}

我想把属性ExampleProperty绑定到一个组合框,这样它就显示了选项“FooBar”和“BarFoo”,并在模式双向工作。最理想的情况下,我希望我的ComboBox定义看起来像这样:

<ComboBox ItemsSource="What goes here?" SelectedItem="{Binding Path=ExampleProperty}" />

目前我有处理程序的组合框。SelectionChanged和ExampleClass。在我手动绑定的窗口中安装了PropertyChanged事件。

有没有更好的或者某种权威的方法?你通常会使用转换器,你将如何填充组合框与正确的值?我现在甚至不想从i18n开始。

Edit

因此,一个问题得到了回答:我如何用正确的值填充组合框。

通过ObjectDataProvider从静态Enum中检索Enum值作为字符串列表。getvalue方法:

<Window.Resources>
    <ObjectDataProvider MethodName="GetValues"
        ObjectType="{x:Type sys:Enum}"
        x:Key="ExampleEnumValues">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="ExampleEnum" />
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</Window.Resources>

这可以作为我的组合框的ItemsSource:

<ComboBox ItemsSource="{Binding Source={StaticResource ExampleEnumValues}}"/>

当前回答

我不知道在xml中是否可行,但请尝试以下方法:

给你的组合框一个名字,这样你就可以在代码背后访问它:"typesComboBox1"

现在试试下面的方法

typesComboBox1.ItemsSource = Enum.GetValues(typeof(ExampleEnum));

其他回答

你可以这样考虑:

define a style for textblock, or any other control you want to use to display your enum: <Style x:Key="enumStyle" TargetType="{x:Type TextBlock}"> <Setter Property="Text" Value="&lt;NULL&gt;"/> <Style.Triggers> <Trigger Property="Tag"> <Trigger.Value> <proj:YourEnum>Value1<proj:YourEnum> </Trigger.Value> <Setter Property="Text" Value="{DynamicResource yourFriendlyValue1}"/> </Trigger> <!-- add more triggers here to reflect your enum --> </Style.Triggers> </Style> define your style for ComboBoxItem <Style TargetType="{x:Type ComboBoxItem}"> <Setter Property="ContentTemplate"> <Setter.Value> <DataTemplate> <TextBlock Tag="{Binding}" Style="{StaticResource enumStyle}"/> </DataTemplate> </Setter.Value> </Setter> </Style> add a combobox and load it with your enum values: <ComboBox SelectedValue="{Binding Path=your property goes here}" SelectedValuePath="Content"> <ComboBox.Items> <ComboBoxItem> <proj:YourEnum>Value1</proj:YourEnum> </ComboBoxItem> </ComboBox.Items> </ComboBox>

如果枚举很大,当然可以在代码中执行相同的操作,从而节省大量输入。 我喜欢这种方法,因为它使本地化变得容易——你定义一次所有的模板,然后,你只更新你的字符串资源文件。

试着用

<ComboBox ItemsSource="{Binding Source={StaticResource ExampleEnumValues}}"
    SelectedValue="{Binding Path=ExampleProperty}" />

看到所有的东西,看到某些过于复杂的解决方案如何成为最琐碎问题的“标准(反)模式”是一件痛苦的事情:应该避免实现MarkupExtension的开销和复杂性,特别是使用属性修饰枚举值。简单地实现一个数据模型。

通常,向用户显示枚举值名称是一个坏主意。枚举不应该显示在UI中。它们是在编程上下文中使用的常量。值名称不用于显示。他们是为了称呼工程师,因此这些名字通常使用特殊的语义和词汇,就像科学词汇一样,不被公众所理解。不要犹豫,为显示的值创建一个专用的源。

当涉及到本地化时,问题变得更加明显。 这就是为什么所有贴出来的答案都是过度设计的。它们使一个非常简单的问题看起来像一个关键问题。 最平凡的解决方案就是最好的解决方案,这是事实。最初问题的主题绝对不是个例外。 我强烈建议不要使用任何提供的答案。尽管它们可能会起作用,但它们会给一个微不足道的问题增加不必要的复杂性。

请注意,您总是可以通过调用静态enum将枚举转换为其值或值名的列表。GetValues或Enum。GetNames,它们都返回一个IEnumerable,你可以直接分配给组合框。ItemsSource属性,例如通过数据绑定。

IEnumerable<ExampleEnum> values = Enum.GetValues<ExampleEnum>();
IEnumerable<string> names = Enum.GetNames<ExampleEnum>();

Usually, when defining an enumeration, you don't have UI in mind. Enumeration value names are not chosen based on UI design rules. Usually, UI labels and text in general are created by people with no developer or programmer background. They usually provide all the required translations to localize the application. There are many good reasons not to mix UI with the application. You would never design a class and name its properties with UI (e.g., DataGrid columns) in mind. You may want your column header to contain whitespaces etc. Same reason why exception messages are directed at developers and not users. You definitely don't want to decorate every property, every exception, enum or whatever data type or member with attributes in order to provide a display name that makes sense to the user in a particular UI context. You don't want to have UI design bleed into your code base and polute your classes. Application and its user interface - this are two different problems. Adding this abstract or virtual extra layer of separation allows e.g., to add enum values that should not be displayed. Or more general, modify code without having to break or modify the UI.

您应该使用一个简单的IValueConverter或一个专门的类来提供这些显示值作为绑定源,而不是使用属性和实现额外的逻辑负载来提取它们的值(使用反射)。 坚持最常见的模式,并为ComboBox项目实现一个数据模型,其中类具有枚举类型的属性作为成员,这有助于您识别ComboBox。SelectedItem(如果你需要枚举值):

ExampleEnum.cs

// Define enumeration without minding any UI elements and context
public enum ExampleEnum 
{ 
    FooBar = 0, 
    BarFoo 
}

ExampleClass.cs

// Define readable enum display values in the UI context.
// Display names can come from a localizable resource.
public class BindingSource : INotifyPropertyChanged
{
    public BindingSource()
    {
        ItemModels = new List<ItemModel> 
        {
            new ItemModel { Label = "Foo Bar Display", Value = ExampleEnum.FooBar },
            new ItemModel { Label = "Bar Foo Display", Value = ExampleEnum.BarFoo }
        }
    }

    public List<ItemModel> ItemModels { get; }

    private ItemModel selectedItemModel;
    public ItemModel SelectedItemModel { get => selectedItemModel; => set and notify; }
}

ItemModel.cs

public class ItemModel
{   
    public string Label { get; set; }
    public ExampleEnum Value { get; set; }
}

MainWindow.xaml

<Window>
  <Window.DataContext>
    <BindingSource />
  </Window.DataContext>

  <ComboBox ItemsSource="{Binding ItemModels}"
            DisplayMemberName="DisplayValue"
            SelectedItem="{Binding SelectedItemModel}" />
</Window>

在视图模型中,你可以有:

public MyEnumType SelectedMyEnumType 
{
    get { return _selectedMyEnumType; }
    set { 
            _selectedMyEnumType = value;
            OnPropertyChanged("SelectedMyEnumType");
        }
}

public IEnumerable<MyEnumType> MyEnumTypeValues
{
    get
    {
        return Enum.GetValues(typeof(MyEnumType))
            .Cast<MyEnumType>();
    }
}

在XAML中,ItemSource绑定到MyEnumTypeValues, SelectedItem绑定到SelectedMyEnumType。

<ComboBox SelectedItem="{Binding SelectedMyEnumType}" ItemsSource="{Binding MyEnumTypeValues}"></ComboBox>

Code

    public enum RULE
    {
        [Description( "Любые, без ограничений" )]
        any,
        [Description( "Любые если будет три в ряд" )]
        anyThree,
        [Description( "Соседние, без ограничений" )]
        nearAny,
        [Description( "Соседние если будет три в ряд" )]
        nearThree
    }

    class ExtendRULE
    {
        public static object Values
        {
            get
            {
                List<object> list = new List<object>();
                foreach( RULE rule in Enum.GetValues( typeof( RULE ) ) )
                {
                    string desc = rule.GetType().GetMember( rule.ToString() )[0].GetCustomAttribute<DescriptionAttribute>().Description;
                    list.Add( new { value = rule, desc = desc } );
                }
                return list;
            }
        }
    }

XAML

<StackPanel>
   <ListBox ItemsSource= "{Binding Source={x:Static model:ExtendRULE.Values}}" DisplayMemberPath="desc" SelectedValuePath="value" SelectedValue="{Binding SelectedRule}"/>
   <ComboBox ItemsSource="{Binding Source={x:Static model:ExtendRULE.Values}}" DisplayMemberPath="desc" SelectedValuePath="value" SelectedValue="{Binding SelectedRule}"/>                        
</StackPanel>