.net 如何使用给定枚举中的所有项目填充 XAML 中的 WPF 组合框?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/538072/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 12:06:29  来源:igfitidea点击:

How can I populate a WPF combo box in XAML with all the items from a given enum?

.netwpfdata-bindingcomboboxenums

提问by Drew Noakes

Say I have an enum with four values:

假设我有一个具有四个值的枚举:

public enum CompassHeading
{
    North,
    South,
    East,
    West
}

What XAML would be required to have a ComboBox be populated with these items?

使用这些项目填充 ComboBox 需要什么 XAML?

<ComboBox ItemsSource="{Binding WhatGoesHere???}" />

Ideally I wouldn't have to set up C# code for this.

理想情况下,我不必为此设置 C# 代码。

回答by casperOne

You can use the ObjectDataProvider to do this:

您可以使用 ObjectDataProvider 来执行此操作:

<ObjectDataProvider MethodName="GetValues" 
    ObjectType="{x:Type sys:Enum}" x:Key="odp">
    <ObjectDataProvider.MethodParameters>
        <x:Type TypeName="local:CompassHeading"/>
    </ObjectDataProvider.MethodParameters>
</ObjectDataProvider>

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

I found the solution here:

我在这里找到了解决方案:

http://bea.stollnitz.com/blog/?p=28

http://bea.stollnitz.com/blog/?p=28

回答by Thomas Levesque

I think using an ObjectDataProvider to do that is really tedious... I have a more concise suggestion (yes I know, it's a bit late...), using a markup extension :

我认为使用 ObjectDataProvider 来做这件事真的很乏味......我有一个更简洁的建议(是的,我知道,它有点晚了......),使用标记扩展:

<ComboBox ItemsSource="{local:EnumValues local:EmployeeType}"/>

Here is the code for the markup extension :

这是标记扩展的代码:

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

回答by rudigrobler

Hereis a detailed example of how to bind to enums in WPF

下面是如何绑定到 WPF 中的枚举的详细示例

Assume you have the following enum

假设您有以下枚举

public enum EmployeeType    
{
    Manager,
    Worker
}

You can then bind in the codebehind

然后您可以在代码隐藏中绑定

typeComboBox.ItemsSource = Enum.GetValues(typeof(EmployeeType));

or use the ObjectDataProvider

或使用 ObjectDataProvider

<ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type sys:Enum}" x:Key="sysEnum">
    <ObjectDataProvider.MethodParameters>
        <x:Type TypeName="local:EmployeeType" />
    </ObjectDataProvider.MethodParameters>
</ObjectDataProvider>

and now you can bind in the markup

现在您可以绑定标记

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

Also check out: Databinding an enum property to a ComboBox in WPF

另请查看: 将枚举属性数据绑定到 WPF 中的 ComboBox

回答by Drew Noakes

For a step-by-step walkthrough of the alternatives and derivations of technique, try this web page:

要逐步了解技术的替代方案和派生方法,请尝试以下网页:

The Missing .NET #7: Displaying Enums in WPF

缺失的 .NET #7:在 WPF 中显示枚举

This article demonstrates a method of overriding the presentation of certain values as well. A good read with plenty of code samples.

本文还演示了一种覆盖某些值的表示的方法。很好的阅读,有大量的代码示例。

回答by Guge

This may be like swearing in a church, but I'd like to declare each ComboBoxItem explicitly in the XAML for the following reasons:

这可能就像在教堂里发誓,但我想在 XAML 中明确声明每个 ComboBoxItem,原因如下:

  • If I need localization I can give the XAML to a translator and keep the code for myself.
  • If I have enum values that aren't suitable for a given ComboBox, I don't have to show them.
  • The order of enums is determined in the XAML, not necessarily in the code.
  • The number of enum values to choose from is usually not very high. I would consider Enums with hundreds of values a code smell.
  • If I need graphics or other ornamentation on some of the ComboBoxItems, it would be easiest to just put it in XAML, where it belongs instead of some tricky Template/Trigger stuff.
  • Keep It Simple, Stupid
  • 如果我需要本地化,我可以将 XAML 提供给翻译人员并为自己保留代码。
  • 如果我有不适合给定 ComboBox 的枚举值,我不必显示它们。
  • 枚举的顺序在 XAML 中确定,不一定在代码中确定。
  • 可供选择的枚举值的数量通常不是很高。我认为具有数百个值的枚举是一种代码味道。
  • 如果我需要在某些 ComboBoxItem 上使用图形或其他装饰,最简单的方法是将它放在 XAML 中,而不是一些棘手的模板/触发器内容。
  • 保持简单,愚蠢

C# Sample code:

C# 示例代码:

    public enum number { one, two, three };

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    private number _number = number.one;
    public number Number
    {
        get { return _number; }
        set {
            if (_number == value)
                return;
            _number = value;
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("Number"));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

XAML code:

XAML 代码:

<Window x:Class="WpfApplication6.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="480" Width="677">
<Grid>
    <ComboBox SelectedValue="{Binding Number}" SelectedValuePath="Tag">
        <ComboBoxItem Content="En" Tag="One"/>
        <ComboBoxItem Content="To" Tag="Two"/>
        <ComboBoxItem Content="Tre" Tag="Three"/>
    </ComboBox>
</Grid>

As you can see, the XAML has been localized to Norwegian, without any need for changes in the C# code.

如您所见,XAML 已本地化为挪威语,无需更改 C# 代码。

回答by Mark

A third solution:

第三种解决方案:

This is slightly more work up-front, better is easier in the long-run if you're binding to loads of Enums. Use a Converter which takes the enumeration's type as a paramter, and converts it to an array of strings as an output.

这需要更多的前期工作,如果您绑定到大量枚举,从长远来看更好更容易。使用将枚举类型作为参数的转换器,并将其转换为字符串数组作为输出。

In VB.NET:

在 VB.NET 中:

Public Class EnumToNamesConverter
    Implements IValueConverter

    Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
        Return [Enum].GetNames(DirectCast(value, Type))
    End Function

    Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
        Throw New NotImplementedException()
    End Function
End Class

Or in C#:

或者在 C# 中:

public sealed class EnumToNamesConverter : IValueConverter
{
  object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
    return Enum.GetNames(value.GetType());
  }

  object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  {
    throw New NotSupportedException()
  }
}

Then in your Application.xaml, add a global resource to access this converter:

然后在你的 中Application.xaml,添加一个全局资源来访问这个转换器:

<local:EnumToNamesConverter x:Key="EnumToNamesConverter" />

Finally use the converter in any XAML pages where you need the values of any Enum...

最后在需要任何枚举值的任何 XAML 页面中使用转换器...

<ComboBox ItemsSource="{Binding
                        Source={x:Type local:CompassHeading},
                        Converter={StaticResource EnumToNamesConverter}}" />