2009-02-11 17 views
22

Say mam enum z czterech wartości:Jak wypełnić pole kombi WPF w XAML wszystkimi elementami z danego wyliczenia?

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

Co XAML będą musiały mieć ComboBox być wypełniany z tych przedmiotów?

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

Idealnie nie musiałbym konfigurować kodu C# do tego.

+0

Właśnie przeczytałem ostatni wpis Eric Burke o klasie Swing JComboBox, która robi to i pomyślał: "Hej, przysięgam, widziałem pytanie SO o tym ..." Byłem blisko, ale chcesz WPF, nie Java/Swing . Tak czy inaczej, tutaj jest dla potomności: http://stuffthathappens.com/blog/2009/02/10/a-swing-jcombobox-for-enums/ – JMD

Odpowiedz

23

Można użyć ObjectDataProvider to zrobić:

<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}}" /> 

znalazłem rozwiązanie tutaj:

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

+0

Dzięki, to rozwiązanie wydaje się dobrze współpracować również z opcją TwoWay. Zauważ, że IsSynchronizedWithCurrentItem = "true" jest czerwonym śledziem dla tego pytania (możesz go usunąć dla jasności innych użytkowników). –

+1

To nie obsługuje lokalizacji. – Guge

+1

@Guge: Nie, nie ma, ale wyliczenia również nie obsługują lokalizacji. Musiałbyś utworzyć inne wyliczenie dla każdej lokalizacji, lub musiałbyś dołączyć atrybut, który mógłby wytworzyć dla ciebie wartości lokalizacyjne (użyłby jakiegoś rodzaju wyszukiwania z kluczem), w takim przypadku pytanie i odpowiedź nie " t stosować już. – casperOne

6

Here jest szczegółowy przykład, w jaki sposób wiążą się teksty stałe w WPF

Załóżmy, że masz następujące wyliczenie:

public enum EmployeeType  
{ 
    Manager, 
    Worker 
} 

Następnie można wiązać w kodzie

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

lub użyj ObjectDataProvider

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

a teraz można wiązać w znacznikach

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

Sprawdź również: Databinding an enum property to a ComboBox in WPF

1

Trzecie rozwiązanie:

To trochę więcej pracy z góry, lepiej jest w dłuższej perspektywie, jeśli wiążesz wiele ładunków. Użyj konwertera, który pobiera typ wyliczenia jako parametr i konwertuje go na tablicę łańcuchów jako wynik.

W 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 

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

Następnie w Application.xaml, dodać zasób globalny dostęp do tego konwertera:

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

wreszcie korzystać konwerter na dowolnych stronach XAML, w których potrzebujesz wartości dowolnego Enum ...

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

Witam maranite2, podoba mi się wygląd tego rozwiązania, ale nie mogłem go uruchomić z wiązaniem TwoWay.Powiązanie działa od kontroli do danych (kiedy zapisuję), ale nie działa z danych do kontroli (pole kombi jest początkowo puste, tam gdzie powinna być wybrana wartość). –

3

Dla poradniku krok po kroku alternatyw oraz indeks techniki, spróbuj tej strony internetowej:

The Missing .NET #7: Displaying Enums in WPF

tym artykule przedstawiono metodę nadrzędne przedstawienie pewnych wartości, jak również . Dobra lektura z dużą ilością próbek kodu.

14

myślę stosując ObjectDataProvider na to jest naprawdę uciążliwe ... Mam sugestię bardziej zwięzły (tak wiem, że to trochę późno ...), używając rozszerzenia znaczników:

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

Oto kod dla rozszerzenia znaczników:

[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

Podszedłem z twoją niemal identyczną klasą, nie widząc twojego. Mine dodaje jeszcze jedną kontrolę: 'enumType.IsEnum' przed instrukcją return. –

3

to może być jak przeklinanie w kościele, ale chciałbym zadeklarować każdą ComboBoxItem wyraźnie w XAML dla następujących powodów:

  • Jeśli potrzebuję lokalizacji, mogę przekazać XAML tłumaczowi i zachować kod dla siebie.
  • Jeśli mam wartości wyliczeniowe, które nie są odpowiednie dla danego elementu ComboBox, nie muszę ich pokazywać.
  • Kolejność wyliczeń określa się w XAML, niekoniecznie w kodzie.
  • Liczba wartości wyliczonych do wyboru zwykle nie jest zbyt duża. Uważałbym, że Enums o setkach wartości ma zapach kodowy.
  • Jeśli potrzebuję grafiki lub innej ornamentyki na niektórych elementach ComboBox, najłatwiej byłoby po prostu umieścić ją w XAML, gdzie należy, zamiast jakiegoś trudnego szablonu/Triggera.
  • Keep It Simple, Głupi

kodu C# próbki: kod

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> 

Jak widać, XAML została zlokalizowana Norweski, bez potrzeby wprowadzania zmian w kodzie C#.

+1

Otrzymujesz wsparcie w zakresie projektowania od razu po wyjęciu z pudełka – surfen