Estoy tratando de encontrar un ejemplo simple donde las enumeraciones se muestran como están. Todos los ejemplos que he visto intentan agregar cadenas de visualización bonitas, pero no quiero esa complejidad.
Básicamente, tengo una clase que contiene todas las propiedades que enlazo, primero configurando el DataContext a esta clase y luego especificando el enlace como este en el archivo xaml:
<ComboBox ItemsSource="{Binding Path=EffectStyle}"/>
Pero esto no muestra los valores de enumeración en los ComboBox
elementos as.
Respuestas:
Puede hacerlo desde el código colocando el siguiente código en el
Loaded
controlador de eventos de Windows , por ejemplo:Si necesita enlazarlo en XAML, debe usarlo
ObjectDataProvider
para crear un objeto disponible como fuente de enlace:Llama la atención sobre el siguiente código:
Guía cómo mapear el espacio de nombres y el ensamblaje que puedes leer en MSDN .
fuente
xmlns:DllAlias="clr-namespace:NamespaceInsideDll; assembly=DllAssemblyName"
XAML para usarlo. Aquí hay una guía: msdn.microsoft.com/en-us/library/ms747086.aspxMe gusta que todos los objetos que estoy vinculando se definan en mi
ViewModel
, así que trato de evitar usarlos<ObjectDataProvider>
en el xaml cuando sea posible.Mi solución no utiliza datos definidos en la Vista ni código subyacente. Solo un DataBinding, un ValueConverter reutilizable, un método para obtener una colección de descripciones para cualquier tipo de Enum y una única propiedad en ViewModel para enlazar.
Cuando quiero vincular un
Enum
a unComboBox
texto que quiero mostrar, nunca coincide con los valores deEnum
, entonces uso el[Description()]
atributo para darle el texto que realmente quiero ver en elComboBox
. Si tuviera una enumeración de días de la semana, se vería así:Primero creé la clase auxiliar con un par de métodos para lidiar con las enumeraciones. Un método obtiene una descripción de un valor específico, el otro método obtiene todos los valores y sus descripciones para un tipo.
A continuación, creamos un
ValueConverter
. Heredar deMarkupExtension
hace que sea más fácil de usar en XAML, por lo que no tenemos que declararlo como un recurso.Mi
ViewModel
sólo tiene 1 propiedad que miView
puede unirse a tanto para elSelectedValue
yItemsSource
del cuadro combinado:Y finalmente para enlazar la
ComboBox
vista (usando elValueConverter
en elItemsSource
enlace) ...Para implementar esta solución, solo necesita copiar mi
EnumHelper
clase y miEnumToCollectionConverter
clase. Trabajarán con cualquier enumeración. Además, no lo incluí aquí, pero laValueDescription
clase es solo una clase simple con 2 propiedades de objeto público, una llamadaValue
, una llamadaDescription
. Puede crearlo usted mismo o puede cambiar el código para usar unTuple<object, object>
oKeyValuePair<object, object>
fuente
ValueDescription
clase que tiene propiedades públicas paraValue
yDescription
Tuple<T1, T2>
ao o enKeyValuePair<TKey, TValue>
lugar de laValueDescription
clase y luego no tendría que crear el suyo.Usé otra solución usando MarkupExtension.
Hice una clase que proporciona elementos de origen:
Eso es casi todo ... Ahora úsalo en XAML:
Cambie 'enumeraciones: Estados' a su enumeración
fuente
e.ToString()
para mostrar el nombre. Puede utilizar su propio traductor, analizador de atributos de descripción, lo que sea.{Binding Path=WhereEverYouWant}
) y si desea que sea compatible con el enlace bidireccional, también tendrá un campo de respaldo. Por lo tanto, no está reemplazando 2 propiedades y 1 campo de respaldo al hacer esto, solo está reemplazando 1 propiedad de solo lectura de una sola línea.Utilice ObjectDataProvider:
y luego enlazar al recurso estático:
basado en este artículo
fuente
xmlns:System="clr-namespace:System;assembly=mscorlib"
La respuesta de Nick realmente me ayudó, pero me di cuenta de que podría modificarse ligeramente, para evitar una clase adicional, ValueDescription. Recordé que ya existe una clase KeyValuePair en el marco, por lo que se puede usar en su lugar.
El código cambia solo ligeramente:
y finalmente el XAML:
Espero que esto sea útil para otros.
fuente
KeyValuePair
pero al final decidí usar aKeyValuePair
para representar algo que no es un par clave-valor solo para evitar escribir una clase trivialmente simple no tenía mucho sentido. LaValueDescription
clase es de solo 5 líneas, y 2 de ellas son justas{
y}
Deberá crear una matriz de valores en la enumeración, que se puede crear llamando a System.Enum.GetValues () , pasándole el
Type
la enumeración de la que desea los elementos.Si especifica esto para la
ItemsSource
propiedad, debe rellenarse con todos los valores de la enumeración. Es posible que desee unirseSelectedItem
aEffectStyle
(suponiendo que es una propiedad de la misma enumeración, y contiene el valor actual).fuente
Todas las publicaciones anteriores han perdido un simple truco. Es posible desde el enlace de SelectedValue descubrir cómo llenar los artículos de origen AUTOMÁTICAMENTE para que su marcado XAML sea justo.
Por ejemplo, en mi ViewModel tengo
ValidateRaiseAndSetIfChanged es mi gancho INPC. El tuyo puede diferir.
La implementación de EnumComboBox es la siguiente, pero primero necesitaré un poco de ayuda para obtener mis cadenas y valores de enumeración
y la clase principal (tenga en cuenta que estoy usando ReactiveUI para enganchar cambios de propiedad a través de WhenAny)
También debe establecer el estilo correctamente en Generic.XAML o su caja no mostrará nada y se arrancará el cabello.
y eso es eso. Obviamente, esto podría extenderse para admitir i18n, pero alargaría la publicación.
fuente
Las aplicaciones universales parecen funcionar de manera un poco diferente; no tiene todo el poder de XAML con todas las funciones. Lo que funcionó para mí es:
Solo por diversión, preparé una pequeña clase con plantillas para ayudar con esto y la publiqué en las páginas de muestras de MSDN . Los bits adicionales me permiten anular opcionalmente los nombres de las enumeraciones y ocultar algunas de las enumeraciones. Mi código se parece mucho al de Nick (arriba), que desearía haber visto antes.
fuente
Hay muchas respuestas excelentes a esta pregunta y presento humildemente la mía. Encuentro que el mío es algo más simple y más elegante. Solo requiere un convertidor de valor.
Dada una enumeración ...
y un convertidor de valor ...
recursos ...
Declaración XAML ...
Ver modelo ...
Cuadro combinado resultante ...
fuente
Debe extender la respuesta de Rogers y Greg con este tipo de convertidor de valor Enum, si está vinculando directamente a las propiedades del modelo de objeto enum.
fuente
Si está vinculado a una propiedad de enumeración real en su ViewModel, no a una representación int de una enumeración, las cosas se ponen difíciles. Descubrí que es necesario vincular a la representación de cadena, NO al valor int como se espera en todos los ejemplos anteriores.
Puede saber si este es el caso vinculando un cuadro de texto simple a la propiedad que desea vincular en su ViewModel. Si muestra texto, enlace a la cadena. Si muestra un número, vincúlelo al valor. Tenga en cuenta que he usado Display dos veces, lo que normalmente sería un error, pero es la única forma en que funciona.
Greg
fuente
Me gustó la respuesta de tom.maruska , pero necesitaba admitir cualquier tipo de enumeración que mi plantilla pudiera encontrar en tiempo de ejecución. Para eso, tuve que usar un enlace para especificar el tipo de la extensión de marcado. Pude trabajar en esta respuesta de nicolay.anykienko para llegar a una extensión de marcado muy flexible que funcionaría en cualquier caso que se me ocurra. Se consume así:
La fuente de la extensión de marcado combinada mencionada anteriormente:
fuente
Explicación simple y clara: http://brianlagunas.com/a-better-way-to-data-bind-enums-in-wpf/
...
...
fuente
Utilizando
ReactiveUI
, he creado la siguiente solución alternativa. No es una solución elegante todo en uno, pero creo que al menos es legible.En mi caso, vincular una lista
enum
a un control es un caso raro, por lo que no necesito escalar la solución a través de la base de código. Sin embargo, el código puede hacerse más genérico cambiandoEffectStyleLookup.Item
a unObject
. Lo probé con mi código, no son necesarias otras modificaciones. Lo que significa que la clase auxiliar podría aplicarse a cualquierenum
lista. Aunque eso reduciría su legibilidad -ReactiveList<EnumLookupHelper>
no tiene un gran sonido.Usando la siguiente clase auxiliar:
En ViewModel, convierta la lista de enumeraciones y exponga como una propiedad:
En el
ComboBox
, utilice laSelectedValuePath
propiedad, para vincular alenum
valor original :En la Vista, esto nos permite vincular el original
enum
alSelectedEffectStyle
ViewModel, pero mostrar elToString()
valor enComboBox
:fuente
Estoy agregando mi comentario (en VB, lamentablemente, pero el concepto se puede replicar fácilmente a C # en un santiamén), porque solo tuve que hacer referencia a esto y no me gustaron las respuestas, ya que eran demasiado complejas. No debería tener que ser tan difícil.
Entonces se me ocurrió una manera más fácil. Vincula los enumeradores a un diccionario. Vincula ese diccionario al cuadro combinado.
Mi cuadro combinado:
Mi código subyacente. Con suerte, esto ayuda a alguien más.
fuente
La solución de Nick se puede simplificar más, sin nada lujoso, solo necesitaría un solo convertidor:
Luego, use esto donde quiera que aparezca su cuadro combinado:
fuente
No recomendaría implementar esto tal como está, pero espero que esto pueda inspirar una buena solución.
Digamos que tu enumeración es Foo. Entonces puedes hacer algo como esto.
Luego, en el
Window.Load
método, puede cargar todas las enumeraciones en unaObservableCollection<FooViewModel>
que puede establecer como el DataContext del cuadro combinado.fuente
Lo mantuve simple. Creé una lista de elementos con los valores de enumeración en mi ViewModel:
En mi código xaml solo necesito esto:
fuente