How to build form at runtime in WPF MVVM based application

606 Views Asked by At

How to build form at runtime in WPF-MVVM (PRISM) based application.

Requirement is like user should be able to add control like textbox, checkbox, combobox etc. at runtime. after adding the crontol user will save the form and all the configuration will get saved in database. So that application can create the form at runtime based on the configuration stored in database.

How can we achieve this?

Thanks.

1

There are 1 best solutions below

0
On

I've done something similar, although not with standard UI controls. I have a series of classes representing the "controls" I want to display - in my scenario these represent physical devices like pumps, valves, switches, displayed on a machinery "control panel" that the user can configure. These classes inherit from a base class (call it "HardwareItem") which exposes some properties that are common to all controls, e.g. Top, Left, Width, Height, Tooltip, etc.

The "designer"

The window where the user "designs" a form consists of the following components:-

  • A "toolbox", basically an ItemsControl bound to a VM List<HardwareItem> property that exposes the available HardwareItems (created and populated by the VM's constructor)

  • A canvas, that the user can drag items onto from the toolbox. When a drop happens, I instantiate the appropriate HardwareItem object and add it to a collection (used to keep track of what controls have been added). To render the control on the canvas, I create a ContentControl and set its "Source" property to the HardwareItem object, then add that to the canvas at the drop position. The control's visual is rendered using XAML DataTemplates that I've created for each HardwareItem type.

  • A PropertyGrid control (part of the free Xceed toolkit). When the user selects a control on the canvas, the corresponding HardwareItem object is wired up to the PropertyGrid, allowing the user set its property values (I use a custom attribute to control which properties should appear in the grid).

When the user clicks "save", I basically just serialize my collection of HardwareItem objects to a string using Json.Net then saved to file.

"Runtime"

To render a previously designed form, the file is deserialized back into a collection of HardwareItem objects, and added to a canvas in pretty much the same way as described above.

Doing something similar with standard WPF controls shouldn't be too dissimilar. You could create classes that expose just the properties that you want a user to manipulate, e.g.:-

// Base class
public class MyControl
{
    public double Top {get;set;}
    public double Left {get;set;}
    public double Width {get;set;}
    public double Height {get;set;}
}

// TextBox
public class MyTextBox : MyControl
{
    public string Text {get;set;}
}

// Button
public class MyButton : MyControl
{
    public string Caption {get;set;}
    public ICommand ClickCommand {get;set;}
}

The DataTemplates might look something like this:-

<DataTemplate DataType="{x:Type MyTextBox}">
    <TextBox Text="{Binding Text}"
             Width={Binding Width}" />
</DataTemplate>
<DataTemplate DataType="{x:Type MyButton}">
    <TextBox Content="{Binding Caption}"
             Width={Binding Width}"
             Height={Binding Height}"
             Command={Binding ClickCommand} />
</DataTemplate>

Much of the canvas manipulation is done in code-behind rather than the VM. It's "UI logic" so is a perfectly acceptable approach.

Prism is not used at all here (I use it for navigating between views, but it doesn't play a part in this "form designer" functionality).