Silverlight 3 DataForm Control Mapping - Add Extensibility

An earlier posting explains how to perform basic modifications to the Silverlight 3 DataForm control.

http://weblogs.asp.net/naughton/archive/2009/08/01/silverlight-3-dataform-control-mapping-basic-modifications.aspx

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:

public IControlMapper ControlMapper { get; set; }

The GenerateField calling code then changes to the following:

private bool GenerateField(PropertyInfo propertyInfo, Type propertyType, string propertyName, BindingMode bindingMode, Panel panel)

...

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

}

 

1 Comment

Comments have been disabled for this content.