The example below is for a DecimalUpDown, but you can use it for all kind of fun stuff. In my github working example you can also see a Textbox.
First we need to add an ElementConvention for out DecimalUpDown in the BootStrapper's Configure method. Override this method and add the following convention (edit 2014-03-26 added attribute check to prevent binding errors):
ConventionManager.AddElementConvention<DecimalUpDown>(DecimalUpDown.ValueProperty, "Value", "ValueChanged").ApplyBinding = (viewModelType, path, property, element, convention) => { if (!ConventionManager.SetBindingWithoutBindingOrValueOverwrite(viewModelType, path, property, element, convention, DecimalUpDown.ValueProperty)) return false; if (property.GetCustomAttributes(typeof (RangeAttribute), true).Any()) { if (!ConventionManager.HasBinding(element, DecimalUpDown.MaximumProperty)) { var binding = new Binding(path) {Mode = BindingMode.OneTime, Converter = RangeMaximumConverter, ConverterParameter = property}; BindingOperations.SetBinding(element, DecimalUpDown.MaximumProperty, binding); } if (!ConventionManager.HasBinding(element, DecimalUpDown.MinimumProperty)) { var binding = new Binding(path) {Mode = BindingMode.OneTime, Converter = RangeMinimumConverter, ConverterParameter = property}; BindingOperations.SetBinding(element, DecimalUpDown.MinimumProperty, binding); } } return true; };As you can see the binding uses a RangeMaximumConverter and a RangeMinimumConverter. These are fairly simple with the AttributeConverter baseclass:
public sealed class RangeMaximumConverter : AttributeConverter<RangeAttribute> { public override object GetValueFromAttribute(RangeAttribute attribute) { return attribute.Maximum; } }And the AttributeConverter base class:
public abstract class AttributeConverter<T> : IValueConverter where T : Attribute { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { var property = parameter as PropertyInfo; if (property == null) return new ArgumentNullException("parameter").ToString(); if (!property.IsDefined(typeof(T), true)) return new ArgumentOutOfRangeException("parameter", parameter, "Property \"" + property.Name + "\" has no associated " + typeof(T).Name + " attribute.").ToString(); return GetValueFromAttribute((T)property.GetCustomAttributes(typeof(T), true)[0]); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotSupportedException(); } public abstract object GetValueFromAttribute(T attribute); }You can find a working example in GitHub.
Happy coding,
Luuk