Próbuję znaleźć prosty przykład, w którym wyliczenia są pokazane w obecnej postaci. Wszystkie przykłady, które widziałem, próbują dodać ładnie wyglądające ciągi wyświetlania, ale nie chcę takiej złożoności.
Zasadniczo mam klasę, która przechowuje wszystkie właściwości, które łączę, najpierw ustawiając DataContext na tę klasę, a następnie określając takie powiązanie w pliku xaml:
<ComboBox ItemsSource="{Binding Path=EffectStyle}"/>
Ale to nie pokazuje wartości wyliczenia w ComboBox
elementach as.
Odpowiedzi:
Możesz to zrobić z kodu, umieszczając następujący kod w module
Loaded
obsługi zdarzeń Windows , na przykład:Jeśli chcesz go powiązać w XAML, musisz użyć,
ObjectDataProvider
aby utworzyć obiekt dostępny jako źródło wiązania:Zwróć uwagę na następny kod:
Przewodnik po mapowaniu przestrzeni nazw i zestawu, którą można czytać w MSDN .
źródło
xmlns:DllAlias="clr-namespace:NamespaceInsideDll; assembly=DllAssemblyName"
XAML, aby go użyć. Oto przewodnik: msdn.microsoft.com/en-us/library/ms747086.aspxPodoba mi się, że wszystkie obiekty, które wiążę, są zdefiniowane w moim
ViewModel
, więc staram się unikać używania<ObjectDataProvider>
w xaml, jeśli to możliwe.Moje rozwiązanie nie wykorzystuje danych zdefiniowanych w widoku i nie zawiera kodu. Tylko DataBinding, ValueConverter wielokrotnego użytku, metoda uzyskiwania kolekcji opisów dla dowolnego typu Enum oraz pojedyncza właściwość w ViewModel do powiązania.
Gdy chcę związać
Enum
zComboBox
tekstem chcę wyświetlić nigdy odpowiada wartościEnum
, więc używam[Description()]
atrybut dać to tekst, który faktycznie chcę widzieć wComboBox
. Gdybym miał wyliczenie dni tygodnia, wyglądałoby to tak:Najpierw stworzyłem klasę pomocnika z kilkoma metodami radzenia sobie z wyliczeniami. Jedna metoda otrzymuje opis konkretnej wartości, druga metoda pobiera wszystkie wartości i ich opisy dla typu.
Następnie tworzymy
ValueConverter
. Dziedziczenie poMarkupExtension
ułatwia korzystanie z XAML, więc nie musimy deklarować go jako zasobu.My
ViewModel
tylko potrzebuje 1 właściwość, że mójView
może wiązać się zarówno dlaSelectedValue
iItemsSource
od combobox:I wreszcie, aby związać
ComboBox
widok (używającValueConverter
wItemsSource
wiążący) ...Aby wdrożyć to rozwiązanie, wystarczy skopiować moją
EnumHelper
klasę iEnumToCollectionConverter
klasę. Będą pracować z dowolnymi wyliczeniami. Ponadto nie uwzględniłem go tutaj, aleValueDescription
klasa jest tylko prostą klasą z 2 właściwościami obiektów publicznych, jedną o nazwieValue
, jedną o nazwieDescription
. Możesz to zrobić samodzielnie lub zmienić kod, aby użyćTuple<object, object>
lubKeyValuePair<object, object>
źródło
ValueDescription
klasę, która ma właściwości publiczneValue
iDescription
Tuple<T1, T2>
lub lubKeyValuePair<TKey, TValue>
zamiast,ValueDescription
i wtedy nie musisz tworzyć własnego.Użyłem innego rozwiązania za pomocą MarkupExtension.
Zrobiłem klasę, która zapewnia źródło przedmiotów:
To prawie wszystko ... Teraz użyj go w XAML:
Zmień „wyliczenia: Stany” na wyliczenie
źródło
e.ToString()
nazwy wyświetlanej. Możesz użyć własnego tłumacza, parsera atrybutów opisu, cokolwiek.{Binding Path=WhereEverYouWant}
), a jeśli chcesz, aby wspierała wiązanie dwukierunkowe, będziesz mieć także pole do tworzenia kopii zapasowych. Robiąc to, nie zastępujesz 2 właściwości i 1 pola bazowego, zastępujesz tylko 1 jednokreskową właściwość tylko do odczytu.Użyj ObjectDataProvider:
a następnie powiąż z zasobem statycznym:
na podstawie tego artykułu
źródło
xmlns:System="clr-namespace:System;assembly=mscorlib"
Odpowiedź Nicka naprawdę mi pomogła, ale zdałem sobie sprawę, że można ją nieco ulepszyć, aby uniknąć dodatkowej klasy, ValueDescription. Przypomniałem sobie, że istnieje już klasa KeyValuePair w ramach, więc można jej użyć zamiast tego.
Kod zmienia się tylko nieznacznie:
i wreszcie XAML:
Mam nadzieję, że jest to pomocne dla innych.
źródło
KeyValuePair
ale ostatecznie zdecydowałem, że użycie aKeyValuePair
do reprezentowania czegoś, co nie jest parą klucz-wartość, aby uniknąć napisania trywialnie prostej klasy, nie miało sensu.ValueDescription
Klasa jest tylko 5 linii, a 2 z nich są po prostu{
i}
Będziesz musiał utworzyć tablicę wartości w wyliczeniu, które można utworzyć, wywołując System.Enum.GetValues () , przekazując je
Type
do wyliczenia, którego chcesz użyć .Jeśli określisz to dla
ItemsSource
właściwości, powinna zostać wypełniona wszystkimi wartościami wyliczenia. Prawdopodobnie chcą wiązaćSelectedItem
sięEffectStyle
(zakładając, że jest własnością tego samego wyliczenia i zawiera aktualną wartość).źródło
Wszystkie powyższe posty przeoczyły prostą sztuczkę. Z powiązania SelectedValue można dowiedzieć się, jak automatycznie wypełnić ItemsSource, aby znaczniki XAML były prawidłowe.
Na przykład w moim ViewModel mam
ValidateRaiseAndSetIfChanged to mój hak INPC. Twoje mogą się różnić.
Implementacja EnumComboBox jest następująca, ale najpierw potrzebuję małego pomocnika, aby uzyskać ciągi i wartości wyliczenia
i główna klasa (uwaga: używam ReactiveUI do przechwytywania zmian właściwości za pośrednictwem WhenAny)
Musisz także poprawnie ustawić styl w Generic.XAML, inaczej twoje pudełko nie będzie renderować niczego i wyciągniesz włosy.
i to jest to. Można to oczywiście rozszerzyć o obsługę i18n, ale wydłużyłoby post.
źródło
Wygląda na to, że aplikacje uniwersalne działają nieco inaczej; nie ma całej mocy w pełni funkcjonalnego XAML. Dla mnie zadziałało:
Dla zabawy przygotowałem małą szabloną klasę, aby w tym pomóc, i opublikowałem ją na stronach próbek MSDN . Dodatkowe bity pozwalają mi opcjonalnie zastąpić nazwy wyliczeń i pozwolić mi ukryć niektóre wyliczenia. Mój kod wygląda okropnie jak kod Nicka (powyżej), który chciałbym zobaczyć wcześniej.
źródło
Istnieje wiele doskonałych odpowiedzi na to pytanie i pokornie przesyłam moje. Uważam, że mój jest nieco prostszy i bardziej elegancki. Wymaga tylko konwertera wartości.
Biorąc pod uwagę wyliczenie ...
i konwerter wartości ...
zasoby...
Deklaracja XAML ...
Zobacz model ...
Powstały combobox ...
źródło
Powinieneś rozszerzyć odpowiedź Rogersa i Grega o tego rodzaju konwerter wartości Enum, jeśli wiążesz bezpośrednio z właściwościami modelu obiektu wyliczeniowego.
źródło
Jeśli wiążesz się z rzeczywistą właściwością wyliczenia na swoim ViewModel, a nie int reprezentacją wyliczenia, sprawy stają się trudne. Stwierdziłem, że konieczne jest powiązanie z reprezentacją ciągu, a NIE wartością int, jak oczekiwano we wszystkich powyższych przykładach.
Możesz stwierdzić, czy tak jest, wiążąc proste pole tekstowe z właściwością, z którą chcesz się połączyć w ViewModel. Jeśli pokazuje tekst, powiąż z łańcuchem. Jeśli pokazuje liczbę, powiąż z wartością. Uwaga: Użyłem Display dwa razy, co normalnie byłoby błędem, ale to jedyny sposób, w jaki działa.
Greg
źródło
Podobała mi się odpowiedź tom.maruska , ale musiałem obsługiwać każdy typ wyliczania, który mój szablon może napotkać w czasie wykonywania. W tym celu musiałem użyć powiązania, aby określić typ rozszerzenia znaczników. Byłem w stanie pracować w tej odpowiedzi z nicolay.anykienko, aby wymyślić bardzo elastyczne rozszerzenie znaczników, które działałoby w każdym przypadku, o jakim tylko mogę pomyśleć. Jest zużywany w następujący sposób:
Źródło wymienionego powyżej rozszerzenia znaczników:
źródło
Proste i jasne wyjaśnienie: http://brianlagunas.com/a-better-way-to-data-bind-enums-in-wpf/
...
...
źródło
Za pomocą
ReactiveUI
utworzyłem następujące alternatywne rozwiązanie. To nie jest eleganckie rozwiązanie typu „wszystko w jednym”, ale myślę, że przynajmniej jest czytelne.W moim przypadku powiązanie listy z
enum
kontrolką jest rzadkim przypadkiem, więc nie muszę skalować rozwiązania w całej bazie kodu. Jednak kod można uczynić bardziej ogólnym, zmieniającEffectStyleLookup.Item
go naObject
. Przetestowałem to z moim kodem, żadne inne modyfikacje nie są konieczne. Co oznacza, że jedną klasę pomocnika można zastosować do dowolnejenum
listy. Chociaż zmniejszyłoby to jego czytelność -ReactiveList<EnumLookupHelper>
nie ma w tym dobrego pierścienia.Korzystanie z następującej klasy pomocniczej:
W ViewModel przekonwertuj listę wyliczeń i ujawnij ją jako właściwość:
W
ComboBox
użyjSelectedValuePath
właściwości, aby powiązać z oryginalnąenum
wartością:W widoku, to pozwala nam wiązać oryginał
enum
doSelectedEffectStyle
w ViewModel, ale wyświetlaToString()
wartość wComboBox
:źródło
Dodam swój komentarz (niestety w VB, ale koncepcja może być łatwo powielona w C # w mgnieniu oka), ponieważ po prostu musiałem się do tego odwoływać i nie podobały mi się żadne odpowiedzi, ponieważ były zbyt skomplikowane. To nie powinno być takie trudne.
Więc wymyśliłem łatwiejszy sposób. Powiąż enumeratory ze słownikiem. Powiąż ten słownik z Combobox.
Mój combobox:
Mój kod. Mam nadzieję, że pomaga to komuś innemu.
źródło
Rozwiązanie Nicka można uprościć bardziej, bez żadnych fantazji, potrzebujesz tylko jednego konwertera:
Następnie użyj tego wszędzie tam, gdzie chcesz, aby wyświetlało się pole kombi:
źródło
Nie zalecałbym wdrażania tego w obecnej formie, ale mam nadzieję, że może to zainspirować dobre rozwiązanie.
Powiedzmy, że twój enum to Foo. Następnie możesz zrobić coś takiego.
Następnie w
Window.Load
metodzie można załadować wszystkie wyliczenia do wartości,ObservableCollection<FooViewModel>
które można ustawić jako DataContext w polu combobox.źródło
Po prostu upraszczałem. Utworzyłem listę elementów z wartościami wyliczenia w moim ViewModel:
W moim kodzie xaml potrzebuję tylko tego:
źródło