Silverlight provides a powerful binding mechanism to allow a comprehensive solution for data transport and validation. Unfortunately, this binding relies on a hard coded model for implementation. In the scenario where the schema of the data entity is not known at compile time, there is nothing provided out of the box.
I have come up with a fairly generic solution that stores data in a dictionary type construct with validation and localization support, leveraging Silverlight’s exiting binding infrastructure.
For this blog post, I will focus on the core classes for binding support, with subsequent updates for validation and localization.
The main class for this solution is the DynamicEntity.
The data and metadata are stored in a private dictionary, and a public indexer overload provides public access directly to the data (necessary for the binding declaration). The key thing to understand here is that binding on a dictionary type object requires collection change notification, not property change notification, to work. I have included property change notification for additional flexibility. The field class contains the field metadata and the value.
public class Field{public FieldMetadata Metadata { get; set; }public object Value { get; set; }}
The field metadata contains properties with meta-information about the field, including name, description, and type. In a future blog post, I will add validators and localization support as well as describe a label control that functions like the SDK Label.
To use this, we can expose the entity as a property in our ViewModel as follows:
public DynamicEntity Entity { get; set; }public MainPage(){Entity = new DynamicEntity();FieldMetadata field = new FieldMetadata(typeof(string), "FirstName", "FirstNameLabel" , "FirstNameDescription", typeof(Strings));field.AddValidator("FirstName", new RequiredValidator("FirstNameRequired")).AddValidator("FirstName", new StringLengthValidator("FirstNameStringLength") { MaximumLength = 40 });Entity.AddField(field, "Carlos");DataContext = this;this.InitializeComponent();}
… and then we bind as follows:
<TextBox x:Name="textBox" Text="{Binding Entity[FirstName], Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnNotifyDataErrors=True}"/>
I will be posting the source code with all the features (validation, localization) on my codeplex site with the last post in this series.