Search code examples
silverlightsilverlight-4.0mvvmmvvm-lightdataform

Dynamically Creating Controls Following MVVM pattern


I'd like to dynamically generate some controls in my silverlight application.
To be more clear, here's a simplified definition of my class:

public class TestClass
{
    [Display(Name="First Name")]
    public string FirstName { get; set; }

    [Display(Name = "Last Name")]
    public string LastName { get; set; }

    public List<CustomProperty> CustomProperties { get; set; }
}

Each "CustomProperty" will finally be a TextBox, CheckBox or ComboBox:

public class CustomProperty
{
    public CustomDataType DataType { get; set; } //enum:integer, string, datetime, etc
    public object Value { get; set; }
    public string DisplayName { get; set; }
    public string Mappings { get; set; } // Simulating enums' behavior.
}
  • What is the best way to implement this using MVVM pattern? If I parse CustomProperties in ViewModel, and find out which controls should be created, How can I create new controls in my view based on MVVM pattern.

  • Is there any silverlight control that can help me make the UI faster?

  • Can I define data annotations programmatically? for example after parsing the custom property, can I add some data annotations (Display, Validation) to the property and bind it to a DataForm, PropertyGrid or a useful control for this situation?

Thank you.


Solution

  • In these cases you usualy use one of the controls inheriting from ItemsControl (e.g. ListBox) or the ItemsControl directly. The controls inheriting from ItemsControl allow you to define a template for each item in a collection, e.g. using your sample (assuming you got access to your TestClass through a view model):

    <ListBox ItemsSource="{Binding TestClass.CustomProperties }">
        <ListBox.ItemContainerStyle>
            <Style TargetType="ListBoxItem">
                <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            </Style>
        </ListBox.ItemContainerStyle>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <!--DataContext is stet to item in the ItemsSource (of type CustomProperty)-->
                <StackPanel>
                    <TextBlock Text="{Binding DisplayName}"/>
                    <TextBox Text="{Binding Value}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    

    This snippet creates a ListBox that contains a label and a text box for each CustonProperty in your CustomProperties collection.