Подтвердить что ты не робот

Как я могу заполнить поле со списком WPF в XAML со всеми элементами из данного перечисления?

Скажем, у меня есть перечисление с четырьмя значениями:

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

Какой XAML потребуется, чтобы ComboBox был заполнен этими элементами?

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

В идеале мне не нужно было бы устанавливать код С# для этого.

4b9b3361

Ответ 1

Вы можете использовать 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}}" />

Я нашел решение здесь:

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

Ответ 2

Я думаю, что использование 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);
    }
}

Ответ 3

Здесь - подробный пример того, как привязывать к перечислениям в 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}}" />

Также проверьте: Связывание свойства enum с ComboBox в WPF

Ответ 4

Пошаговое руководство по альтернативам и выводам техники попробуйте эту веб-страницу:

Отсутствует .NET # 7: Отображение перечислений в WPF

В этой статье демонстрируется метод переопределения представления некоторых значений. Хорошее чтение с большим количеством примеров кода.

Ответ 5

Это может быть как клятва в церкви, но я хотел бы объявить каждый ComboBoxItem явно в XAML по следующим причинам:

  • Если мне нужна локализация, я могу передать XAML переводчику и сохранить код для себя.
  • Если у меня есть значения перечисления, которые не подходят для данного ComboBox, я не должен их показывать.
  • Порядок перечислений определяется в XAML, не обязательно в коде.
  • Количество значений перечисления на выбор обычно не очень велико. Я бы рассмотрел Enums с сотнями значений запаха кода.
  • Если мне нужна графика или другое украшение на некоторых из ComboBoxItems, было бы проще просто поместить его в XAML, где он принадлежит, а не какой-то сложный материал Template/Trigger.
  • Держите его простым, глупым

С# Пример кода:

    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 был локализован на норвежском языке, без каких-либо изменений в коде С#.

Ответ 6

Третье решение:

Это немного больше работы вперёд, лучше в долгосрочной перспективе, если вы привязываетесь к нагрузкам Enums. Используйте конвертер, который вводит тип перечисления в качестве параметра и преобразует его в массив строк в качестве вывода.

В 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

Или в С#:

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

Затем в вашем Application.xaml добавьте глобальный ресурс для доступа к этому конвертеру:

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

Наконец, используйте конвертер на любых страницах XAML, где вам нужны значения любого Enum...

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