Sebagai contoh, ambil kode berikut:
public enum ExampleEnum { FooBar, BarFoo }
public class ExampleClass : INotifyPropertyChanged
{
private ExampleEnum example;
public ExampleEnum ExampleProperty
{ get { return example; } { /* set and notify */; } }
}
Saya ingin databind properti ExampleProperty ke ComboBox, sehingga itu menunjukkan opsi "FooBar" dan "BarFoo" dan bekerja dalam mode TwoWay. Secara optimal saya ingin definisi ComboBox saya terlihat seperti ini:
<ComboBox ItemsSource="What goes here?" SelectedItem="{Binding Path=ExampleProperty}" />
Saat ini saya memiliki penangan untuk acara ComboBox.SelectionChanged dan ExampleClass.PropertyChanged diinstal di Window saya di mana saya melakukan penjilidan secara manual.
Apakah ada cara kanonik yang lebih baik atau semacamnya? Apakah Anda biasanya menggunakan Pengonversi dan bagaimana Anda mengisi ComboBox dengan nilai yang benar? Saya bahkan tidak ingin memulai dengan i18n sekarang.
Edit
Jadi satu pertanyaan dijawab: Bagaimana cara mengisi ComboBox dengan nilai yang benar.
Ambil nilai Enum sebagai daftar string melalui ObjectDataProvider dari metode Enum.GetValues statis:
<Window.Resources>
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="ExampleEnumValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="ExampleEnum" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
Ini bisa saya gunakan sebagai ItemsSource untuk ComboBox saya:
<ComboBox ItemsSource="{Binding Source={StaticResource ExampleEnumValues}}"/>
Jawaban:
Anda dapat membuat ekstensi markup kustom.
Contoh penggunaan:
Di bagian atas XAML Anda:
lalu...
Dan implementasinya ...
sumber
ItemsSource
param. Untuk menjaga agar tampilan dan model tetap terpisah saya perlu membuat salinan enumerasi dalam ViewModel dan kode ViewModel untuk menerjemahkan di antara keduanya ... Yang akan membuat solusi tidak sesederhana itu lagi. Atau adakah cara untuk memasok tipe itu sendiri dari ViewModel?Dalam model tampilan Anda dapat memiliki:
Di XAML
ItemSource
mengikat keMyEnumTypeValues
danSelectedItem
mengikat keSelectedMyEnumType
.sumber
Saya lebih suka tidak menggunakan nama enum di UI. Saya lebih suka menggunakan nilai yang berbeda untuk pengguna (
DisplayMemberPath
) dan berbeda untuk nilai (enum dalam kasus ini) (SelectedValuePath
). Kedua nilai tersebut dapat dikemasKeyValuePair
dan disimpan dalam kamus.XAML
C #
EDIT: Kompatibel dengan pola MVVM.
sumber
Enum.GetValues
, tetapi itu tidak akan menyelesaikan bagian dari nama yang akan ditampilkan. Pada akhirnya, dan khususnya jika I18n diimplementasikan, Anda harus mengubah hal-hal secara manual jika enum berubah. Tetapi enum tidak seharusnya sering berubah, jika memang demikian, bukan? +1public Dictionary<ExampleEnum, string> ExampleEnumsWithCaptions { get; } = new Dictionary<ExampleEnum, string>() { {ExampleEnum.FooBar, "Foo Bar"}, {ExampleEnum.BarFoo, "Reversed Foo Bar"}, //{ExampleEnum.None, "Hidden in UI"}, };
Saya tidak tahu apakah mungkin hanya di XAML tetapi coba yang berikut ini:
Beri nama ComboBox Anda sehingga Anda dapat mengaksesnya di codebehind: "typesComboBox1"
Sekarang coba yang berikut ini
sumber
Berdasarkan jawaban yang diterima tetapi sekarang dihapus yang disediakan oleh ageektrapped, saya membuat versi langsing tanpa beberapa fitur yang lebih canggih. Semua kode disertakan di sini untuk memungkinkan Anda menyalin-menempelnya dan tidak diblokir oleh tautan-busuk.
Saya menggunakan
System.ComponentModel.DescriptionAttribute
yang benar-benar dimaksudkan untuk deskripsi waktu desain. Jika Anda tidak suka menggunakan atribut ini, Anda dapat membuatnya sendiri, tetapi saya pikir menggunakan atribut ini benar-benar menyelesaikan pekerjaan. Jika Anda tidak menggunakan atribut, nama akan default ke nama nilai enum dalam kode.Berikut adalah kelas yang digunakan sebagai sumber item:
Anda dapat menggunakannya di XAML seperti ini:
sumber
Gunakan ObjectDataProvider:
dan kemudian ikat ke sumber daya statis:
Temukan solusi ini di blog ini
sumber
Converter
enum-to-string.Cara favorit saya untuk melakukan ini adalah dengan
ValueConverter
sehingga ItemsSource dan SelectedValue keduanya mengikat ke properti yang sama. Ini tidak memerlukan properti tambahan untuk menjaga ViewModel Anda tetap bagus dan bersih.Dan definisi Konverter:
Konverter ini akan bekerja dengan enum apa pun.
ValueDescription
hanya kelas sederhana denganValue
properti danDescription
properti. Anda bisa dengan mudah menggunakan aTuple
denganItem1
danItem2
, atauKeyValuePair
denganKey
danValue
alih-alih Nilai dan Deskripsi atau kelas lain pilihan Anda asalkan itu dapat memiliki nilai enum dan deskripsi string dari nilai enum itu.sumber
ValueDescription
kelas,Description
properti dapat dihilangkan jika tidak diperlukan. Kelas sederhana dengan hanyaValue
properti juga berfungsi!.Select(e => e.ToString())
, alih-alih menggunakanValueDescription
kelas.ValueDescription
jugaKeyValuePair
bisa digunakan, seperti yang ditunjukkan di siniBerikut ini adalah solusi umum menggunakan metode pembantu. Ini juga dapat menangani enum dari jenis apa pun yang mendasarinya (byte, sbyte, uint, long, dll.)
Metode Penolong:
Lihat Model:
Kotak kombo:
sumber
Anda dapat mempertimbangkan sesuatu seperti itu:
tentukan style untuk textblock, atau kontrol lain yang ingin Anda gunakan untuk menampilkan enum Anda:
tentukan gaya Anda untuk ComboBoxItem
tambahkan kotak kombo dan muat dengan nilai enum Anda:
jika enum Anda besar, tentu saja Anda dapat melakukan hal yang sama dalam kode, menghemat banyak mengetik. Saya suka pendekatan itu, karena itu membuat lokalisasi mudah - Anda mendefinisikan semua template sekali, dan kemudian, Anda hanya memperbarui file sumber daya string Anda.
sumber
Jika Anda menggunakan MVVM, berdasarkan jawaban @rudigrobler Anda dapat melakukan hal berikut:
Tambahkan properti berikut ke kelas ViewModel
Kemudian di XAML lakukan hal berikut:
sumber
Ini adalah
DevExpress
jawaban spesifik berdasarkan jawaban terpilih teratasGregor S.
(saat ini memiliki 128 suara).Ini berarti kami dapat menjaga gaya konsisten di seluruh aplikasi:
Sayangnya, jawaban asli tidak bekerja dengan
ComboBoxEdit
dari DevExpress tanpa beberapa modifikasi.Pertama, XAML untuk
ComboBoxEdit
:Tidak perlu dikatakan, Anda harus menunjuk
xamlExtensions
pada namespace yang berisi kelas ekstensi XAML (yang didefinisikan di bawah):Dan kita harus menunjuk
myEnum
pada namespace yang berisi enum:Kemudian, enum:
Masalah dengan XAML adalah bahwa kita tidak dapat menggunakan
SelectedItemValue
, karena ini melempar kesalahan karena setter tidak dapat diakses (sedikit kelalaian pada bagian Anda,DevExpress
). Jadi kita harus memodifikasi kitaViewModel
untuk mendapatkan nilai langsung dari objek:Untuk kelengkapan, berikut adalah ekstensi XAML dari jawaban asli (sedikit diganti namanya):
Penafian: Saya tidak memiliki afiliasi dengan DevExpress. Telerik juga merupakan perpustakaan yang bagus.
sumber
Coba gunakan
sumber
Saya telah membuat proyek CodePlex open source yang melakukan ini. Anda dapat mengunduh paket NuGet dari sini .
sumber