gawicks
gawicks

Reputation: 1964

Databinding Attribute values to a combobox

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

Answers (1)

McGarnagle
McGarnagle

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

Related Questions