Silverlight 3 DataForm Control Mapping - Add Extensibility
An earlier posting explains how to perform basic modifications to the Silverlight 3 DataForm control.
It's convenient if such features are available for extensibility.
This can be achieved in a straightforward fashion too. (A modified DataForm project is attached.)
The DataForm implements the GenerateField method, which calls the two methods that affect Control mapping.Control control = GetControlFromType(propertyType); DependencyProperty dependencyProperty = GetBindingPropertyFromType(propertyType);
We can refactor this area, by introducing a Control Mapping interface (IControlMapper) and a default implementation (ControlMapper).
Note: I wanted access to the Custom Attributes on each Property, since Custom Attributes may contain information that influences the Control Mapping process. As such, I tweaked the GenerateField method signature to accept the PropertyInfo for the current Property.
We add a property to DataForm:
The GenerateField calling code then changes to the following:
...
IControlMapper controlMapper = this.ControlMapper;if (null == controlMapper){
controlMapper =
new ControlMapper();}
controlMapper.PropertyInfo = propertyInfo;
controlMapper.PropertyType = propertyType;
Control control = controlMapper.GetControl(); DependencyProperty dependencyProperty = controlMapper.GetBindingProperty();...
We can now define a derived DataForm class that supplies a different implementation of IControlMapper that performs the required mapping.
public interface IControlMapper{
PropertyInfo PropertyInfo { get; set; } Type PropertyType { get; set; }Control GetControl(); DependencyProperty GetBindingProperty();}
Here is the refactored ControlMapper base class:
public class ControlMapper : IControlMapper{
#region IControlMapper Members protected PropertyInfo propertyInfo;public PropertyInfo PropertyInfo{
get{
return this.propertyInfo;}
set{
this.propertyInfo = value;}
}
protected Type propertyType;public Type PropertyType{
get{
return this.propertyType;}
set{
this.propertyType = value;}
}
public virtual Control GetControl(){
Type type = this.PropertyType; Debug.Assert(type != null, "The type must not be null.");if (type == typeof(bool)){
return new CheckBox();}
else if (type == typeof(bool?)){
CheckBox checkBox = new CheckBox();checkBox.IsThreeState =
true;return checkBox;}
else if (type == typeof(DateTime) || type == typeof(DateTime?)){
return new DatePicker();}
else if (type.IsEnum){
ComboBox comboBox = new ComboBox(); FieldInfo[] valueFieldInfos = type.GetFields(BindingFlags.Public | BindingFlags.Static);List<string> valueList = new List<string>();foreach (FieldInfo valueFieldInfo in valueFieldInfos){
Enum value = valueFieldInfo.GetValue(null) as Enum;if (value != null){
valueList.Add(value.ToString());
}
}
comboBox.ItemsSource = valueList;
return comboBox;}
else{
return new TextBox();}
}
public virtual DependencyProperty GetBindingProperty(){
Type type = this.PropertyType; Debug.Assert(type != null, "The type must not be null.");if (type == typeof(bool) || type == typeof(bool?)){
return CheckBox.IsCheckedProperty;}
else if (type == typeof(DateTime) || type == typeof(DateTime?)){
return DatePicker.SelectedDateProperty;}
else if (type.IsEnum){
return ComboBox.SelectedItemProperty;}
else{
return TextBox.TextProperty;}
}
#endregion
}