Dynamically Creating Controls Following MVVM patte

2020-07-18 11:06发布

问题:

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.

回答1:

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.