Как я могу заполнить поле со списком WPF в XAML всеми элементами из данного перечисления? - PullRequest
22 голосов
/ 11 февраля 2009

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

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

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

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

В идеале мне не пришлось бы устанавливать код C # для этого.

Ответы [ 6 ]

23 голосов
/ 11 февраля 2009

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

14 голосов
/ 11 мая 2009

Я думаю, что использование 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);
    }
}
6 голосов
/ 12 февраля 2009

Здесь - подробный пример привязки к перечислениям в WPF

Предположим, у вас есть следующее перечисление

public enum EmployeeType    
{
    Manager,
    Worker
}

Затем вы можете связать в коде позади

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

3 голосов
/ 03 сентября 2010

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

  • Если мне нужна локализация, я могу передать XAML переводчику и сохранить код для себя.
  • Если у меня есть значения enum, которые не подходят для данного ComboBox, мне не нужно их показывать.
  • Порядок перечислений определяется в 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 был локализован на норвежский язык без каких-либо изменений в коде C #.

3 голосов
/ 12 февраля 2009

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

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

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

1 голос
/ 12 февраля 2009

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

Это немного сложнее, чем раньше, тем лучше в долгосрочной перспективе, если вы привязаны к нагрузкам 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

Или в 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()
  }
}

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

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

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

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