Reputation: 1964
I have a set of classes with a set of properties like this; Each having a custom attribute indicating the possible values it could take. Is there anyway to databind these values to a combobox instead of hardcoding using <ComboBoxItem/>
?
[Values("Cash","Bank","Not Applicable")]
public Nullable<int> PaymentMethod{ get; set; }
Edit: My attribute looks like this
class ValuesAttribute:Attribute
{
public List<string> values { get; set; }
public ValuesAttribute(params String[] values)
{
this.values= new List<string>();
foreach (var v in values)
{
this.values.Add(v);
}
}
}
Upvotes: 1
Views: 374
Reputation: 102763
I would use a converter for this. Send it the underlying object and the property name as the parameter. Return a key/value array so that you can bind both the value (index/enum value) and display text:
<ComboBox ItemsSource="{Binding ConverterParameter='PaymentMethod',Converter={StaticResource AttributeConverter}}"
DisplayMemberPath="Value" SelectedValuePath="Key"
/>
The converter can then get the values using reflection:
public class AttributeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null && parameter as string != null)
{
var property = value.GetType().GetProperty((string)parameter);
if (property != null)
{
var attribute = property.GetCustomAttributes(typeof(ValuesAttribute), false).OfType<ValuesAttribute>().FirstOrDefault();
if (attribute != null)
return attribute.values.Select((display, index) =>
new KeyValuePair<int, string>(index, display)
).ToArray();
}
}
return DependencyProperty.UnsetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Note: if you need to do this a lot in your application, it might be worthwhile subclassing ComboBox, or creating a Behavior that applies the relevant properties.
Upvotes: 1