Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 如何用给定枚举中的所有项填充XAML中的WPF组合框?_.net_Wpf_Data Binding_Combobox_Enums - Fatal编程技术网

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

.net 如何用给定枚举中的所有项填充XAML中的WPF组合框?,.net,wpf,data-binding,combobox,enums,.net,Wpf,Data Binding,Combobox,Enums,假设我有一个具有四个值的枚举: public enum CompassHeading { North, South, East, West } 使用这些项填充组合框需要什么XAML <ComboBox ItemsSource="{Binding WhatGoesHere???}" /> 理想情况下,我不必为此设置C#代码。您可以使用ObjectDataProvider来执行此操作: <ObjectDataProvider MethodNa

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

public enum CompassHeading
{
    North,
    South,
    East,
    West
}
使用这些项填充组合框需要什么XAML

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


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

您可以使用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}}" />

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

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

假设您有以下枚举

public enum EmployeeType    
{
    Manager,
    Worker
}
然后,您可以绑定到codebehind中

typeComboBox.ItemsSource = Enum.GetValues(typeof(EmployeeType));
或者使用ObjectDataProvider

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

现在可以在标记中进行绑定

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

另外,请查看: 第三种解决方案:

如果您绑定到大量的枚举,那么前面的工作会稍微多一些,从长远来看会更好。使用以枚举类型为参数的转换器,并将其转换为字符串数组作为输出

在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
或者在C#中:

然后在
应用程序.xaml
中,添加一个全局资源以访问此转换器:

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

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

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

要逐步了解技术的替代品和衍生产品,请尝试以下网页:


本文还演示了重写某些值的表示的方法。阅读大量代码示例非常好。

我认为使用ObjectDataProvider来实现这一点非常乏味。。。我有一个更简洁的建议(是的,我知道,有点晚了…),使用标记扩展:

<ComboBox ItemsSource="{local:EnumValues local:EmployeeType}"/>
[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中明确声明每个ComboBoxItem,原因如下:

  • 如果我需要本地化,我可以将XAML提供给翻译器,并为自己保留代码
  • 如果我有不适合给定组合框的枚举值,我就不必显示它们
  • 枚举的顺序在XAML中确定,不一定在代码中确定
  • 要从中选择的枚举值的数量通常不是很高。我会考虑Enums有数百个值的代码气味。
  • 如果我需要一些ComboBoxItems上的图形或其他装饰,最简单的方法是将它放在XAML中,而不是放在一些复杂的模板/触发器中
  • 保持简单,笨蛋
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代码:

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


正如您所见,XAML已经本地化为Norwegian,无需更改C代码。

我刚刚读了Eric Burke关于Swing JComboBox类的最新文章,并认为“嘿,我发誓我看到了一个关于这个的问题……”我很接近,但您想要的是WPF,而不是Java/Swing。无论如何,这是给后代的:谢谢,这个解决方案似乎也适用于双向绑定。请注意,IsSynchronizedWithCurrentItem=“true”是这个问题的一个挡箭牌(为了澄清其他访问者,您可能希望删除它)。它不支持本地化。@Guge:不,它不支持,但枚举也不支持本地化。您必须为每个区域创建一个不同的枚举,或者必须附加一个可以为您生成本地化值的属性(它将使用某种键控查找),在这种情况下,问题和答案不再适用。@casperOne:没错!我不认为枚举是用户界面的一部分,只是一种在代码中消除整数符号使用的方法。以这种方式使枚举对用户可见会有层分离不良的味道。@Guge:也许吧,但这对提出问题的人来说更重要,不是吗?这个问题非常具体,当我回答它时,背后的原因并不重要。嗨,maranite2,我喜欢这个解决方案的外观,但我无法让它与双向绑定一起工作。绑定可以从控件到数据(当我保存时)工作,但不能从数据到控件工作(组合框最初是空白的,应该有一个选择的值)。您可以从这个框中获得设计时支持。我为您提供了一个几乎完全相同的类,而不需要查看您的类。Mine在return语句之前再添加一个检查:
enumType.IsEnum
<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>