Jako przykład weź następujący kod:
public enum ExampleEnum { FooBar, BarFoo }
public class ExampleClass : INotifyPropertyChanged
{
private ExampleEnum example;
public ExampleEnum ExampleProperty
{ get { return example; } { /* set and notify */; } }
}
Chcę, aby powiązać dane właściwość ExampleProperty z ComboBox, aby wyświetlał opcje „FooBar” i „BarFoo” i działa w trybie TwoWay. Optymalnie chcę, aby moja definicja ComboBox wyglądała mniej więcej tak:
<ComboBox ItemsSource="What goes here?" SelectedItem="{Binding Path=ExampleProperty}" />
Obecnie mam moduły obsługi zdarzeń ComboBox.SelectionChanged i ExampleClass.PropertyChanged zainstalowane w moim oknie, w którym ręcznie wykonuję powiązanie.
Czy istnieje lepszy lub jakiś kanoniczny sposób? Czy zwykle używałbyś Konwerterów i jak wypełniłbyś ComboBox odpowiednimi wartościami? Nie chcę nawet teraz zacząć korzystać z i18n.
Edytować
Tak więc odpowiedziano na jedno pytanie: Jak wypełnić ComboBox odpowiednimi wartościami.
Pobierz wartości Enum jako listę łańcuchów za pomocą ObjectDataProvider ze statycznej metody Enum.GetValues:
<Window.Resources>
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="ExampleEnumValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="ExampleEnum" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
Tego mogę użyć jako ItemsSource dla mojego ComboBox:
<ComboBox ItemsSource="{Binding Source={StaticResource ExampleEnumValues}}"/>
Odpowiedzi:
Możesz utworzyć niestandardowe rozszerzenie znaczników.
Przykład użycia:
U góry XAML:
i wtedy...
I wdrożenie ...
źródło
ItemsSource
parametrze. Aby zachować widok i model oddzielony, musiałbym utworzyć kopię wyliczenia w ViewModel i kod ViewModel w celu przetłumaczenia między tymi dwoma ... Co sprawiłoby, że rozwiązanie nie byłoby już takie proste. Czy jest sposób na dostarczenie samego typu z ViewModel?W viewmodel możesz mieć:
W XAML
ItemSource
wiąże sięMyEnumTypeValues
iSelectedItem
wiąże się zSelectedMyEnumType
.źródło
Wolę nie używać nazwy enum w interfejsie użytkownika. Wolę użyć innej wartości dla user (
DisplayMemberPath
) i innej wartości (enum w tym przypadku) (SelectedValuePath
). Te dwie wartości można spakowaćKeyValuePair
i zapisać w słowniku.XAML
DO#
EDYCJA: Kompatybilny ze wzorem MVVM.
źródło
Enum.GetValues
, ale nie rozwiązałoby to części nazw do wyświetlenia. Na koniec, a zwłaszcza jeśli I18n jest zaimplementowany, i tak będziesz musiał ręcznie zmieniać rzeczy, jeśli zmienia się wyliczenie. Ale wyliczenia nie powinny się często zmieniać, jeśli w ogóle, prawda? +1public Dictionary<ExampleEnum, string> ExampleEnumsWithCaptions { get; } = new Dictionary<ExampleEnum, string>() { {ExampleEnum.FooBar, "Foo Bar"}, {ExampleEnum.BarFoo, "Reversed Foo Bar"}, //{ExampleEnum.None, "Hidden in UI"}, };
Nie wiem, czy jest to możliwe tylko w XAML, ale spróbuj wykonać następujące czynności:
Nadaj ComboBoxowi nazwę, abyś mógł uzyskać do niej dostęp w codebehind: „typesComboBox1”
Teraz spróbuj wykonać następujące czynności
źródło
W oparciu o zaakceptowaną, ale teraz usuniętą odpowiedź udostępnioną przez ageektrapped , stworzyłem wersję uproszczoną bez niektórych bardziej zaawansowanych funkcji. Cały kod jest tu zawarty, abyś mógł go skopiować i wkleić, a nie zostać zablokowany przez link-rot.
Używam tego,
System.ComponentModel.DescriptionAttribute
co naprawdę jest przeznaczone do opisu czasu projektowania. Jeśli nie lubisz używać tego atrybutu, możesz stworzyć swój własny, ale myślę, że użycie tego atrybutu naprawdę wykona zadanie. Jeśli nie użyjesz tego atrybutu, nazwa domyślnie przyjmuje nazwę wartości wyliczonej w kodzie.Oto klasa używana jako źródło przedmiotów:
Możesz go używać w XAML w następujący sposób:
źródło
Użyj ObjectDataProvider:
a następnie powiąż z zasobem statycznym:
Znajdź to rozwiązanie na tym blogu
źródło
Converter
problem z wyliczaniem do łańcucha.Moim ulubionym sposobem na to jest
ValueConverter
, aby zarówno ItemsSource, jak i SelectedValue były powiązane z tą samą właściwością. Nie wymaga to żadnych dodatkowych właściwości, aby Twój ViewModel był ładny i czysty.I definicja konwertera:
Ten konwerter będzie działał z dowolnym wyliczeniem.
ValueDescription
to tylko prosta klasa zValue
właściwością iDescription
właściwością. Możesz równie łatwo użyćTuple
zItem1
iItem2
, lubKeyValuePair
zKey
iValue
zamiast wartości i opisu lub dowolnej innej wybranej przez ciebie klasy, pod warunkiem, że może ona zawierać wartość wyliczenia i opis ciągu tej wartości wyliczenia.źródło
ValueDescription
klasyDescription
właściwość można pominąć, jeśli nie jest potrzebna.Value
Działa również prosta klasa z tylko właściwością!.Select(e => e.ToString())
Zamiast używaćValueDescription
klasy.ValueDescription
równieżKeyValuePair
można użyć, jak pokazano tutajOto ogólne rozwiązanie z wykorzystaniem metody pomocniczej. Może to również obsługiwać wyliczanie dowolnego typu bazowego (bajt, sbyte, uint, long itp.)
Metoda pomocnicza:
Zobacz model:
ComboBox:
źródło
możesz rozważyć coś takiego:
zdefiniuj styl dla bloku tekstowego lub innego elementu sterującego, którego chcesz użyć do wyświetlenia wyliczenia:
zdefiniuj swój styl dla ComboBoxItem
dodaj combobox i załaduj go wartościami wyliczenia:
jeśli twoje wyliczenie jest duże, możesz oczywiście zrobić to samo w kodzie, oszczędzając dużo pisania. Podoba mi się to podejście, ponieważ ułatwia lokalizację - wszystkie szablony definiuje się raz, a następnie aktualizuje się tylko pliki zasobów ciągów.
źródło
Jeśli używasz MVVM, na podstawie odpowiedzi @rudigrobler możesz wykonać następujące czynności:
Dodaj następującą właściwość do klasy ViewModel
Następnie w XAML wykonaj następujące czynności:
źródło
To jest
DevExpress
konkretna odpowiedź na podstawie najczęściej głosowanej odpowiedziGregor S.
(obecnie ma 128 głosów).Oznacza to, że możemy zachować spójność stylizacji w całej aplikacji:
Niestety oryginalna odpowiedź nie działa z
ComboBoxEdit
DevExpress bez pewnych modyfikacji.Po pierwsze, XAML dla
ComboBoxEdit
:Nie trzeba dodawać, że trzeba będzie wskazać
xamlExtensions
przestrzeń nazw, która zawiera klasę rozszerzeń XAML (zdefiniowaną poniżej):I musimy wskazać
myEnum
przestrzeń nazw, która zawiera wyliczenie:Następnie wyliczenie:
Problem z XAML polega na tym, że nie możemy użyć
SelectedItemValue
, ponieważ powoduje to błąd, ponieważ konfigurator jest niedostępny (trochę niedopatrzenia z twojej stronyDevExpress
). Musimy więc zmodyfikować nasz,ViewModel
aby uzyskać wartość bezpośrednio z obiektu:Dla kompletności, oto rozszerzenie XAML z oryginalnej odpowiedzi (nieco zmieniona):
Uwaga: Nie mam powiązań z DevExpress. Telerik to także świetna biblioteka.
źródło
Spróbuj użyć
źródło
Stworzyłem projekt CodePlex typu open source , który to robi. Możesz pobrać pakiet NuGet stąd .
źródło