c# - significa - Enlace de datos WPF: ¿Cómo se vinculan los datos a una caja combinada usando XAML?
que significa alt en una imagen (4)
Aquí hay una solución: crea una propiedad (una lista) que contiene todas las posibilidades y vincula su ComboBox en esa propiedad.
En el XAML:
<ComboBox
Name="ScopeComboBox"
Width="120"
Height="23"
Margin="12"
ItemsSource="{Binding Path=AccountDetailsProperty}"
DisplayMemberPath="Value"/>
Y en el código detrás:
public partial class Window1 : Window
{
public Window1()
{
AccountDetailsProperty = new List<AccountDetail>()
{
new AccountDetail(DetailScope.Business, "Business"),
new AccountDetail(DetailScope.OtherDetail, "Other details"),
new AccountDetail(DetailScope.Private, "Private"),
};
InitializeComponent();
this.DataContext = this;
}
public List<AccountDetail> AccountDetailsProperty { get; set; }
}
Esta pregunta ya tiene una respuesta aquí:
Tengo una clase:
public class AccountDetail
{
public DetailScope Scope
{
get { return scope; }
set { scope = value; }
}
public string Value
{
get { return this.value; }
set { this.value = value; }
}
private DetailScope scope;
private string value;
public AccountDetail(DetailScope scope, string value)
{
this.scope = scope;
this.value = value;
}
}
y una enumeración:
public enum DetailScope
{
Private,
Business,
OtherDetail
}
Por último, tengo un archivo .xaml:
<Window x:Class="Gui.Wpf.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test"
SizeToContent="WidthAndHeight">
<Grid>
<ComboBox
Name="ScopeComboBox"
Width="120"
Height="23"
Margin="12" />
</Grid>
</Window>
Me gustaría hacer dos cosas:
- Deseo que los datos
DetailsScope
valores enum deDetailsScope
valores del cuadro combinado. No deseo enlazar valores enum directamente porque el último valor enum seríaOtherDetail
lugar deOther detail
(se agregó un carácter de espacio y una letra pequeña ''d''). - Deseo que los datos enlacen el valor seleccionado en el cuadro combinado al especificado en la instancia del objeto
AccountDetail
.
¿Podrías ayudarme? Gracias.
Actualización: Encontré esta publicación http://blogs.msdn.com/b/wpfsdk/archive/2007/02/22/displaying-enum-values-using-data-binding.aspx . Necesito algo similar.
La forma en que siempre lo he hecho es la siguiente. La belleza de esta solución es que es completamente genérica y puede reutilizarse para cualquier tipo de enumeración.
1) Cuando defines una enumeración, utiliza algunos atributos personalizados para dar un poco de información. En este ejemplo, he usado Browsable (falso) para indicar que este enumerador es interno, y no quiero ver esta opción en un cuadro combinado. Descripción ("") me permite especificar un nombre para mostrar para la enumeración.
public enum MyEnumerationTypeEnum
{
[Browsable(false)]
Undefined,
[Description("Item 1")]
Item1,
[Description("Item 2")]
Item2,
Item3
}
2) Defina una clase a la que he llamado EnumerationManager. Esta es una clase genérica que analiza un tipo de enumeración y genera una lista de valores. Si un enumerador tiene Browsable establecido en falso, se saltará. Si tiene un atributo Descripción, usará la cadena de descripción como nombre para mostrar. Si no se encuentra una descripción, solo mostrará la cadena predeterminada del enumerador.
public class EnumerationManager
{
public static Array GetValues(Type enumeration)
{
Array wArray = Enum.GetValues(enumeration);
ArrayList wFinalArray = new ArrayList();
foreach(Enum wValue in wArray)
{
FieldInfo fi = enumeration.GetField(wValue.ToString());
if(null != fi)
{
BrowsableAttribute[] wBrowsableAttributes = fi.GetCustomAttributes(typeof(BrowsableAttribute),true) as BrowsableAttribute[];
if(wBrowsableAttributes.Length > 0)
{
// If the Browsable attribute is false
if(wBrowsableAttributes[0].Browsable == false)
{
// Do not add the enumeration to the list.
continue;
}
}
DescriptionAttribute[] wDescriptions = fi.GetCustomAttributes(typeof(DescriptionAttribute),true) as DescriptionAttribute[];
if(wDescriptions.Length > 0)
{
wFinalArray.Add(wDescriptions[0].Description);
}
else
wFinalArray.Add(wValue);
}
}
return wFinalArray.ToArray();
}
}
3) En su xaml agregue una sección en su ResourceDictionary
<ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type l:EnumerationManager}" x:Key="OutputListForMyComboBox">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="l:MyEnumerationTypeEnum" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
4) Ahora solo une el ItemsSource de tu cuadro combinado a esta clave que acabamos de definir en el diccionario de recursos
<ComboBox Name="comboBox2"
ItemsSource="{Binding Source={StaticResource OutputListForMyComboBox}}" />
Si prueba este código utilizando mi enumeración anterior, debería ver 3 elementos en su cuadro combinado:
Item 1
Item 2
Item3
Espero que esto ayude.
EDITACIONES: si agrega la implementación de LocalizableDescriptionAttribute y la usa en su lugar, el atributo Description que estaba usando sería perfecto.
Una forma bastante sencilla de hacerlo es utilizar un ObjectDataProvider
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="DetailScopeDataProvider">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:DetailScope" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
Utilice ObjectDataProvider como ItemsSource para ComboBox, enlace SelectedItem a la propiedad Scope y aplique un convertidor para la visualización de cada ComboBoxItem
<ComboBox Name="ScopeComboBox"
ItemsSource="{Binding Source={StaticResource DetailScopeDataProvider}}"
SelectedItem="{Binding Scope}"
Width="120"
Height="23"
Margin="12">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource CamelCaseConverter}}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Y en el convertidor puede usar Regex para el divisor de cadenas CamelCase que se encuentra en this pregunta. Usé la versión más avanzada, pero probablemente puedas usar una más simple. OtherDetail + la expresión regular = Otro detalle. Hacer que el valor de retorno sea más bajo y luego devolver una cadena con el primer carácter. UpperCase debería darte el resultado esperado
public class CamelCaseConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string enumString = value.ToString();
string camelCaseString = Regex.Replace(enumString, "([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]))", "$1 ").ToLower();
return char.ToUpper(camelCaseString[0]) + camelCaseString.Substring(1);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value;
}
}
Yo usaría un convertidor de valor para esto, esto te permitirá unir directamente usando el convertidor, puedes cambiar la implementación Convert para hacer una presentación "más agradable" legible por humanos de las enumeraciones, es decir, dividir en caracteres en mayúscula.
Hay un artículo completo sobre este enfoque here .
public class MyEnumToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (MyEnum) Enum.Parse( typeof ( MyEnum ), value.ToString(), true );
}
}