Saya mencoba untuk menemukan contoh sederhana di mana enums ditampilkan sebagaimana adanya. Semua contoh yang saya lihat mencoba menambahkan string tampilan yang terlihat bagus tapi saya tidak ingin kompleksitas itu.
Pada dasarnya saya memiliki kelas yang menampung semua properti yang saya ikat, dengan terlebih dahulu mengatur DataContext ke kelas ini, dan kemudian menentukan pengikatan seperti ini di file xaml:
<ComboBox ItemsSource="{Binding Path=EffectStyle}"/>
Tapi ini tidak menunjukkan nilai enum di ComboBox
item sebagai.
Jawaban:
Anda dapat melakukannya dari kode dengan menempatkan kode berikut di Window
Loaded
event handler, misalnya:Jika Anda perlu mengikatnya di XAML, Anda perlu menggunakan
ObjectDataProvider
untuk membuat objek yang tersedia sebagai sumber yang mengikat:Menarik perhatian pada kode selanjutnya:
Panduan bagaimana memetakan namespace dan assembly yang dapat Anda baca di MSDN .
sumber
xmlns:DllAlias="clr-namespace:NamespaceInsideDll; assembly=DllAssemblyName"
XAML untuk menggunakannya. Berikut ini panduan: msdn.microsoft.com/en-us/library/ms747086.aspxSaya suka untuk semua objek yang saya ikat harus didefinisikan di saya
ViewModel
, jadi saya mencoba untuk menghindari menggunakan<ObjectDataProvider>
xaml jika memungkinkan.Solusi saya tidak menggunakan data yang ditentukan dalam Lihat dan tidak ada kode di belakang. Hanya DataBinding, ValueConverter yang dapat digunakan kembali, metode untuk mendapatkan koleksi deskripsi untuk semua jenis Enum, dan satu properti di ViewModel untuk diikat.
Ketika saya ingin mengikat sebuah
Enum
keComboBox
teks saya ingin menampilkan tidak pernah cocok dengan nilai-nilaiEnum
, jadi saya menggunakan[Description()]
atribut untuk memberikan teks yang sebenarnya ingin saya lihat diComboBox
. Jika saya memiliki enum hari dalam seminggu, itu akan terlihat seperti ini:Pertama saya membuat kelas pembantu dengan beberapa metode untuk menangani enum. Satu metode mendapatkan deskripsi untuk nilai tertentu, metode lain mendapatkan semua nilai dan deskripsi mereka untuk suatu tipe.
Selanjutnya, kita buat a
ValueConverter
. Mewarisi dariMarkupExtension
membuatnya lebih mudah digunakan di XAML sehingga kami tidak harus mendeklarasikannya sebagai sumber daya.ViewModel
Satu-satunya kebutuhan saya adalah 1 properti yangView
dapat saya ikat untuk keduanyaSelectedValue
danItemsSource
kotak kombo:Dan akhirnya untuk mengikat
ComboBox
tampilan (menggunakanValueConverter
dalamItemsSource
ikatan) ...Untuk mengimplementasikan solusi ini, Anda hanya perlu menyalin
EnumHelper
kelas danEnumToCollectionConverter
kelas saya. Mereka akan bekerja dengan enum apa pun . Juga, saya tidak memasukkannya di sini, tetapiValueDescription
kelas ini hanya kelas sederhana dengan 2 properti objek publik, satu disebutValue
, satu disebutDescription
. Anda dapat membuatnya sendiri atau Anda dapat mengubah kode untuk menggunakan aTuple<object, object>
atauKeyValuePair<object, object>
sumber
ValueDescription
kelas yang memiliki properti publik untukValue
danDescription
Tuple<T1, T2>
atauKeyValuePair<TKey, TValue>
bukanValueDescription
dan kemudian Anda tidak perlu membuatnya sendiri.Saya menggunakan solusi lain menggunakan MarkupExtension.
Saya membuat kelas yang menyediakan sumber item:
Itu hampir semua ... Sekarang gunakan di XAML:
Ubah 'enums: Nyatakan' ke enum Anda
sumber
e.ToString()
nama tampilan. Anda dapat menggunakan penerjemah Anda sendiri, pengurai atribut keterangan, apa pun.{Binding Path=WhereEverYouWant}
) dan jika Anda ingin mendukung pengikatan 2 arah, Anda juga akan memiliki bidang dukungan. Jadi Anda tidak mengganti 2 properti dan 1 bidang dukungan dengan melakukan ini, Anda hanya mengganti 1 properti hanya baca satu baris.Gunakan ObjectDataProvider:
dan kemudian ikat ke sumber daya statis:
berdasarkan artikel ini
sumber
xmlns:System="clr-namespace:System;assembly=mscorlib"
Jawaban Nick benar-benar membantu saya, tetapi saya menyadari itu bisa sedikit diubah, untuk menghindari kelas tambahan, ValueDescription. Saya ingat bahwa sudah ada kelas KeyValuePair yang sudah ada dalam framework, jadi ini bisa digunakan.
Kode hanya berubah sedikit:
dan akhirnya XAML:
Saya harap ini bermanfaat bagi orang lain.
sumber
KeyValuePair
tetapi pada akhirnya saya memutuskan menggunakan aKeyValuePair
untuk mewakili sesuatu yang bukan pasangan kunci-nilai hanya untuk menghindari penulisan kelas sederhana yang sepele tidak masuk akal. TheValueDescription
kelas hanya 5 baris, dan 2 dari mereka hanya{
dan}
Anda harus membuat array nilai di enum, yang dapat dibuat dengan memanggil System.Enum.GetValues () , meneruskannya
Type
dengan enum yang Anda inginkan dari item.Jika Anda menentukan ini untuk
ItemsSource
properti, maka itu harus diisi dengan semua nilai enum. Anda mungkin ingin mengikatSelectedItem
keEffectStyle
(dengan asumsi itu adalah properti dari enum yang sama, dan mengandung nilai saat ini).sumber
Semua posting di atas telah melewatkan trik sederhana. Dimungkinkan dari pengikatan SelectedValue untuk mengetahui cara mengisi ItemSource secara OTOMATIS sehingga markup XAML Anda adil.
Sebagai contoh di ViewModel saya yang saya miliki
ValidateRaiseAndSetIfChanged adalah kait INPC saya. Milik Anda mungkin berbeda.
Implementasi EnumComboBox adalah sebagai berikut, tetapi pertama-tama saya perlu sedikit pembantu untuk mendapatkan string dan nilai enumerasi saya.
dan kelas utama (Catatan saya menggunakan ReactiveUI untuk mengaitkan perubahan properti melalui WhenAny)
Anda juga perlu mengatur gaya dengan benar di Generic.XAML atau kotak Anda tidak akan membuat apa pun dan Anda akan mencabut rambut Anda.
dan itu dia. Ini jelas dapat diperluas untuk mendukung i18n tetapi akan membuat posting lebih lama.
sumber
Aplikasi universal tampaknya bekerja sedikit berbeda; itu tidak memiliki semua kekuatan XAML berfitur lengkap. Apa yang berhasil untuk saya adalah:
Hanya untuk bersenang-senang saya menyiapkan kelas templated kecil untuk membantu dengan ini dan menerbitkannya ke halaman Sampel MSDN . Bit tambahan membiarkan saya secara opsional mengganti nama enum dan membiarkan saya menyembunyikan beberapa enum. Kode saya terlihat seperti Nick (di atas), yang saya harap telah saya lihat sebelumnya.
sumber
Ada banyak jawaban bagus untuk pertanyaan ini dan saya dengan rendah hati mengirimkan pertanyaan saya. Saya menemukan bahwa milik saya agak lebih sederhana dan lebih elegan. Ini hanya membutuhkan konverter nilai.
Diberikan enum ...
dan konverter nilai ...
sumber daya ...
Deklarasi XAML ...
Lihat model ...
Menghasilkan kotak kombo ...
sumber
Anda harus memperluas jawaban Rogers dan Greg dengan semacam konverter nilai Enum, jika Anda mengikat langsung ke properti model objek.
sumber
Jika Anda mengikat ke properti enum aktual di ViewModel Anda, bukan representasi int dari enum, segalanya menjadi rumit. Saya menemukan perlu untuk mengikat ke representasi string, BUKAN nilai int seperti yang diharapkan dalam semua contoh di atas.
Anda dapat mengetahui apakah ini masalahnya dengan mengikat kotak teks sederhana ke properti yang ingin Anda ikat pada ViewModel Anda. Jika menampilkan teks, ikat ke string. Jika itu menunjukkan angka, ikat ke nilainya. Catatan Saya telah menggunakan Tampilan dua kali yang biasanya merupakan kesalahan, tapi itu satu-satunya cara kerjanya.
Greg
sumber
Saya menyukai jawaban tom.maruska , tetapi saya perlu mendukung semua jenis enum yang mungkin ditemui templat saya saat runtime. Untuk itu, saya harus menggunakan penjilidan untuk menentukan jenis ke ekstensi markup. Saya bisa bekerja dalam jawaban ini dari nicolay.anykienko untuk datang dengan ekstensi markup yang sangat fleksibel yang akan bekerja dalam hal apa pun yang dapat saya pikirkan. Dikonsumsi seperti ini:
Sumber untuk ekstensi markup tumbuk yang dirujuk di atas:
sumber
Penjelasan sederhana dan jelas: http://brianlagunas.com/a-better-way-to-data-bind-enums-in-wpf/
...
...
sumber
Dengan menggunakan
ReactiveUI
, saya telah membuat solusi alternatif berikut. Ini bukan solusi all-in-one yang elegan, tapi saya pikir paling tidak itu bisa dibaca.Dalam kasus saya, mengikat daftar
enum
ke kontrol adalah kasus yang jarang terjadi, jadi saya tidak perlu skala solusi di seluruh basis kode. Namun, kode dapat dibuat lebih umum dengan mengubahEffectStyleLookup.Item
menjadiObject
. Saya mengujinya dengan kode saya, tidak ada modifikasi lain yang diperlukan. Yang berarti satu kelas helper dapat diterapkan keenum
daftar mana pun . Meskipun itu akan mengurangi keterbacaannya -ReactiveList<EnumLookupHelper>
tidak memiliki cincin yang bagus untuk itu.Menggunakan kelas pembantu berikut:
Di ViewModel, konversi daftar enum dan paparkan sebagai properti:
Di
ComboBox
, manfaatkanSelectedValuePath
properti, untuk mengikat ke nilai aslienum
:Dalam View, ini memungkinkan kita untuk mengikat aslinya
enum
keSelectedEffectStyle
dalam ViewModel, tetapi menampilkanToString()
nilai dalamComboBox
:sumber
Saya menambahkan komentar saya (dalam VB, sayangnya, tetapi konsepnya dapat dengan mudah direplikasi ke C # dalam sekejap), karena saya hanya perlu referensi ini dan tidak menyukai jawaban karena mereka terlalu kompleks. Seharusnya tidak sesulit ini.
Jadi saya menemukan cara yang lebih mudah. Ikat Enumerator ke dalam Kamus. Bind kamus itu ke Combobox.
Kotak kombo saya:
Kode saya di belakang. Semoga ini bisa membantu orang lain keluar.
sumber
Solusi Nick dapat lebih disederhanakan, tanpa ada yang mewah, Anda hanya perlu satu konverter:
Anda kemudian menggunakan ini di mana pun Anda ingin kotak kombo Anda muncul:
sumber
Saya tidak akan merekomendasikan menerapkan ini sebagaimana adanya tapi mudah-mudahan ini dapat menginspirasi solusi yang baik
Katakanlah enum Anda adalah Foo. Maka Anda dapat melakukan sesuatu seperti ini.
Kemudian pada
Window.Load
metode Anda dapat memuat semua enums keObservableCollection<FooViewModel>
yang Anda dapat mengatur sebagai DataContext dari combobox.sumber
Saya hanya membuatnya sederhana. Saya membuat daftar item dengan nilai enum di ViewModel saya:
Dalam kode xaml saya, saya hanya perlu ini:
sumber