2009-02-11 3 views
22

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

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

Что XAML необходимо будет иметь ComboBox быть заселен с этими предметами?

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

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

+0

Я только что прочитал недавнее сообщение Эрика Берка о классе Swing JComboBox, который делает это, и подумал: «Эй, клянусь, я увидел вопрос SO об этом ...» Я был близок, но вы хотите WPF, а не Java/Swing , Во всяком случае, здесь для потомков: http://stuffthathappens.com/blog/2009/02/10/a-swing-jcombobox-for-enums/ – JMD

ответ

23

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

+0

Спасибо, это решение, похоже, хорошо работает с привязкой TwoWay. Обратите внимание, что IsSynchronizedWithCurrentItem = "true" - это красная селедка для этого вопроса (вы можете удалить его для ясности других посетителей). –

+1

Это не поддерживает локализацию. – Guge

+1

@Guge: Нет, это не так, но перечисления также не поддерживают локализацию. Вам нужно было бы создать другое перечисление для каждого местоположения, или вам нужно было бы прикрепить атрибут, который мог бы произвести для вас значения локализации (он использовал бы какой-то определенный ключ), и в этом случае вопрос и ответ наденьте, t применить. – casperOne

6

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

Также проверьте: Databinding an enum property to a ComboBox in WPF

1

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

Это немного более эффективная работа, лучше в долгосрочной перспективе, если вы привязаны к нагрузкам 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}}" /> 
+0

Привет, maranite2, мне нравится внешний вид этого решения, но я не мог заставить его работать с привязкой TwoWay.Связывание работает с контролем на данные (при сохранении), но оно не работает с данными для управления (поле со списком изначально пустое, где должно быть выбрано значение). –

3

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

The Missing .NET #7: Displaying Enums in WPF

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

14

Я думаю, что с помощью 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); 
    } 
} 
+0

Я придумал почти точный класс для вас, не увидев вас. Mine добавляет еще одну проверку: 'enumType.IsEnum' перед оператором return. –

3

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

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

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

+1

И вы получаете поддержку времени разработки из коробки – surfen

Смежные вопросы