Dynamically Generating Forms in WPF and Silverlight

Introduction

In this article you will learn how to generate WPF forms dynamically from property fields. Suppose we have a requirement to create a WPF form. First, we'll begin with how to create a form in XAML.

Creating forms at Design Time in XAML

The following form shows how to create form in XAML:

<Grid Margin="10">

    <Grid.ColumnDefinitions>

        <ColumnDefinition Width="100" />

        <ColumnDefinition Width="*" />

    </Grid.ColumnDefinitions>

             

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto" />

        <RowDefinition Height="Auto" />

        <RowDefinition Height="Auto" />

        <RowDefinition Height="*" />

    </Grid.RowDefinitions>

 

    <TextBlock Text="First Name" Height="19"  Margin="0,7,31,4" />           

    <TextBox x:Name="FirstName" Margin="3"  Grid.Row="0" Grid.Column="1" />

             

    <TextBlock Text="Last Name" Margin="0,7,6,3" Grid.Row="1" Height="20" />

    <TextBox x:Name="LastName" Margin="3" Grid.Row="1" Grid.Column="1" />  

 

    <TextBlock Text="EmailId" Grid.Row="2" Margin="0,9,0,0" Height="21" />

<TextBox x:Name=" EmailId " Margin="3" Grid.Row="1" Grid.Column="1" />  

 

    <Button x:Name="Save" Grid.Row="3" Grid.Column="3" HorizontalAlignment="Right"

            VerticalAlignment="Top" Margin="3" Width="80" Height="25" Content="Save" />

</Grid>

The following diagram shows how the form looks.

Clipboard01.jpg

Creating forms at runtime using XAML strings

The following example shows how to create a form at runtime by using the property class.

Create a person class with 10 properties.  

public class Person

{

    public string FirstName { getset; }

    public string LastName { getset; }

    public bool isDefault { getset; }

    public string EmailId { getset; }

    public string EmployeeNo { getset; }

    public string Age { getset; }

 

    public string EmailId2 { getset; }

    public bool isMale { getset; }

    public string MobileNo { getset; }

    public string TelephoneNo { getset; }

}

Creating Controls at runtime

We created the following functions for a creating textbox, textblock, row definition and for checkbox. Here the functions CreateCheckBox() creates a checkbox at runtime. 

And the following code will create a text block.

private TextBlock CreateTextBlock(string text, int row, int column)
{
    string[] aa = BreakUpperCB(text);
    string prop = "";
    for (int i = 0; i < aa.Length; i++)
    {
        prop = prop +" "+ aa[i];
    }

    TextBlock
 tb = new TextBlock() { Text = prop, Margin = new Thickness(5, 8, 0, 5) };
    tb.MinWidth = 90;
    tb.FontWeight = FontWeights.Bold;            
  
    tb.Margin = new Thickness(5);
    var bc = new BrushConverter();
    tb.Foreground = Brush)bc.ConvertFrom("#FF2D72BC");
    Grid.SetColumn(tb, column);
    Grid.SetRow(tb, row);          
    return tb;
}

Handling Events Dynamically

void button_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Saved Successfully");
}
private Button CreateButton(string text, int row, int column )
{
    Button tb = new Button() { Content = text, VerticalAlignment =VerticalAlignment.Top, 
    HorizontalAlignment = HorizontalAlignment.Left, Margin = new Thickness(5, 8, 0, 5) };
    tb.Width = 90;
    tb.Height = 25;
    tb.Margin = new Thickness(5);
    Grid.SetColumn(tb, column);
    Grid.SetRow(tb, row);           
    return tb;
}

private TextBox CreateTextBox( int row, int column)
{
    TextBox tb = new TextBox();
    tb.Margin = new Thickness(5);
    tb.Height = 22;
    tb.Width = 150;
    Grid.SetColumn(tb, column);
    Grid.SetRow(tb, row);
    return tb;
}

// this will break the property text by upper
public string[] BreakUpperCB(string sInput)

{

    StringBuilder[] sReturn = new StringBuilder[1];

    sReturn[0] = new StringBuilder(sInput.Length);

    const string CUPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    int iArrayCount = 0;

    for (int iIndex = 0; iIndex < sInput.Length; iIndex++)

    {

        string sChar = sInput.Substring(iIndex, 1); // get a char

        if ((CUPPER.Contains(sChar)) && (iIndex > 0))

        {

            iArrayCount++;

            System.Text.StringBuilder[] sTemp = new System.Text.StringBuilder[iArrayCount + 1];

            Array.Copy(sReturn, 0, sTemp, 0, iArrayCount);

            sTemp[iArrayCount] = new StringBuilder(sInput.Length);

            sReturn = sTemp;

        }

        sReturn[iArrayCount].Append(sChar);

    }

    string[] sReturnString = new string[iArrayCount + 1];

    for (int iIndex = 0; iIndex < sReturn.Length; iIndex++)

    {

        sReturnString[iIndex] = sReturn[iIndex].ToString();

    }

    return sReturnString;

}

 

public partial class MainWindow : Window

{

    public MainWindow()

    {

        InitializeComponent();

    }

 

    private void Grid_Loaded(object sender, RoutedEventArgs e)

    {

        Person obj = new Person();

        obj.FirstName = "sujeet";

        CreateControls (obj);

    }

}

Create Controls

In the following example we create a function CreateControlsUsingObjects(Person obj) that creates a dynamic form.

This method creates controls dynamically based on the properties. 

In the following example we have read the properties from the Person Class and we add controls to the form:

private void CreateControls(Person obj)
{
    
List<Person> objList=new List<Person>();
     objList.Add(obj);
    
Grid rootGrid = new Grid();
     rootGrid.Margin =
new Thickness(10.0);
     rootGrid.ColumnDefinitions.Add(
       
new ColumnDefinition() { Width = new GridLength(100.0) });
     rootGrid.ColumnDefinitions.Add(
         
new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
     rootGrid.ColumnDefinitions.Add(
        
new ColumnDefinition() { Width = new GridLength(100.0) });
     rootGrid.ColumnDefinitions.Add(
        
new ColumnDefinition() { Width = new GridLength(100.0) });
    
PropertyInfo[] propertyInfos;
     propertyInfos =
typeof(Person).GetProperties();
     rootGrid.RowDefinitions.Add(CreateRowDefinition());
    
int j = 1;
    
foreach (PropertyInfo propertyInfo in propertyInfos)
     {
    
    if (propertyInfo.PropertyType.Name == "String")
         {
             rootGrid.RowDefinitions.Add(CreateRowDefinition());
            
var Label = CreateTextBlock(propertyInfo.Name, j, 0);
             rootGrid.Children.Add(Label);
            
var Textbox = CreateTextBox(j, 1);
             rootGrid.Children.Add(Textbox);
             j++;
        }
        
if (propertyInfo.PropertyType.Name == "Boolean")
        {
            rootGrid.RowDefinitions.Add(CreateRowDefinition());
            
var Label = CreateTextBlock(propertyInfo.Name, j, 0);
            rootGrid.Children.Add(Label);
            
var Textbox =  CreateCheckBox(j, 1);
            rootGrid.Children.Add(Textbox);
            j++;
        }
    }
    rootGrid.RowDefinitions.Add(CreateRowDefinition());
    
var Button = CreateButton("Save",j + 1, 1);
    Button.Click +=
new RoutedEventHandler(button_Click);
    rootGrid.Children.Add(Button);
    LayoutRoot.Children.Add(rootGrid)
}


In the above example we have shown how to create a WPF form dynamically.

Output

Clipboard02.jpg

Summary

In this way we have shown how to create dynamic forms in WPF or Silverlight.

Good luck and please, let me know your feedback!

I hope you like it. Thanks.