Skip to main content

ViewBuilder

Namespace: Wisej.Web.Ext.ViewBuilder

Assembly: Wisej.Web.Ext.ViewBuilder (4.1.0.0)

Creates a view (a ContainerControl instance) or loads an existing one from a JSON representation or from an object model.

public static class ViewBuilder

Each object in the definition describes a component: the "_type" member contains the type name (a name without a namespace, i.e. "TextBox", is resolved in the Wisej.Web namespace of Wisej.Framework; otherwise use the full name, i.e. "MyApp.Controls.MyPanel"), and all the other members are assigned to the properties with the same name. Property names are matched ignoring case, therefore both camel casing ("labelText") and proper casing ("LabelText") work. The "_type" member is not needed on the root object when loading into an existing container with LoadView.

Values are converted to the property type using the property's TypeConverter, i.e. "10,10" for a Point or "Top" for an enum. Arrays are added to collection properties such as "controls". A string assigned to a property that refers to another object (i.e. "dataSource" or "acceptButton") is resolved after the whole view is loaded to the control or component with that name (see also ResolveReference). A string in the format {Binding Member, Source=name, Format=format, OnFormat=handler, OnParse=handler, SourceUpdateMode=mode, ControlUpdateMode=mode} creates a data binding; all the parts except the member are optional and the default data source is the root container.

Members with the name of an event are attached to the event handler with the specified name. The handler is resolved using ResolveEventHandler first, then it's looked up among the methods declared by the class of the root container, and last it's resolved as a fully qualified static method name (i.e. "MyApp.Handlers.OnClick"). Event handlers are not compiled from code: to support code snippets, assign a custom ResolveEventHandler.

The optional "components" array on the root object defines non-visual components (i.e. a ToolTip or an ErrorProvider) that are created first and are disposed together with the root container. Extender properties provided by these components are assigned using the component name and the property name separated by an underscore or a dot, i.e. "toolTip1_ToolTip". Declare the "components" array as the last member of the root object: the root members that follow it are not processed.

Example:

Loading a view defined in JSON into an existing form, with an event handler and a tool tip:

public partial class Form1 : Form
{
private void Form1_Load(object sender, EventArgs e)
{
this.LoadView(@"{
""text"": ""Customer"",
""size"": ""400,300"",
""controls"": [
{
""_type"": ""TextBox"",
""name"": ""textBox1"",
""dock"": ""Top"",
""labelText"": ""Name:"",
""validating"": ""textBox1_Validating"",
""toolTip1_ToolTip"": ""Enter the name""
},
{
""_type"": ""Panel"",
""dock"": ""Top"",
""autoSize"": true,
""controls"": [
{
""_type"": ""TextBox"",
""name"": ""textBox2"",
""location"": ""10,10"",
""labelText"": ""Last Name:""
}
]
}
],
""components"": [
{ ""_type"": ""ToolTip"", ""name"": ""toolTip1"" }
]
}");
}

private void textBox1_Validating(object sender, CancelEventArgs e)
{
e.Cancel = String.IsNullOrEmpty(((TextBox)sender).Text);
}
}

Binding controls to a property of the root container (the default data source):

public partial class CustomerForm : Form
{
public Customer Customer { get; set; }

public void LoadCustomer(Customer customer)
{
this.Customer = customer;
this.LoadView(@"{
""controls"": [
{ ""_type"": ""TextBox"", ""dock"": ""Top"", ""text"": ""{Binding Customer.Name}"" },
{ ""_type"": ""TextBox"", ""dock"": ""Top"", ""readOnly"": true, ""text"": ""{Binding Customer.Balance, Format=c}"" }
]
}");
}
}

Fields​

NameTypeDescriptionValue
ResolveEventHandlerFunc<Object, EventDescriptor, String, MethodInfo>Resolves the value in name to a MethodInfo that can be attached to the event defined as descriptor .
ResolveReferenceFunc<ContainerControl, Object, String, String, Object>Resolves the name of component to the corresponding instance. It's invoked by the parser after the view has been loaded and names assigned to control properties need to be resolved.

Methods​

Static member Create(json)​

Creates a new ContainerControl from the specified json representation.

ParameterTypeDescription
jsonStringJSON definition of the ContainerControl to create.

Returns: ContainerControl. The new ContainerControl instance of the type specified in the "_type" member of the root object.

The root type must derive from ContainerControl, i.e. "Form", "Page" or "UserControl", and have a public parameterless constructor. Event handler names are looked up among the methods declared by the root type, therefore set "_type" to the full name of your own class (i.e. "MyApp.CustomerForm") to use its handlers.

Throws:

Example:

Creating and showing a form defined in JSON:

var form = (Form)ViewBuilder.Create(@"{
""_type"": ""Form"",
""text"": ""Hello"",
""size"": ""300,200"",
""controls"": [
{ ""_type"": ""Label"", ""text"": ""Hello World!"", ""dock"": ""Fill"" }
]
}");
form.Show();

Static member Create(json)​

Creates a new ContainerControl from the JSON representation read from the specified json stream.

ParameterTypeDescription
jsonStreamStream containing the JSON definition of the ContainerControl to create.

Returns: ContainerControl. The new ContainerControl instance of the type specified in the "_type" member of the root object.

The stream is read but not closed.

Throws:

Example:

Creating a page from a JSON file deployed with the application:

using (var stream = File.OpenRead(Application.MapPath("Views/Dashboard.json")))
{
var page = (Page)ViewBuilder.Create(stream);
page.Show();
}

Static member Create(model)​

Creates a new ContainerControl from the specified model representation.

ParameterTypeDescription
modelObjectObject model of the ContainerControl to create.

Returns: ContainerControl. The new ContainerControl instance of the type specified in the "_type" member of the root object.

The model is accessed dynamically: the root object and every nested object that defines a component must support the string indexer used to read the "_type" member, like DynamicObject or the objects returned by Parse.

Throws:

Example:

Creating a form from a DynamicObject model:

dynamic button = new DynamicObject();
button._type = "Button";
button.text = "OK";
button.location = "10,10";

dynamic model = new DynamicObject();
model._type = "Form";
model.text = "Confirm";
model.controls = new object[] { button };

var form = (Form)ViewBuilder.Create((object)model);
form.ShowDialog();

Static member LoadView(container, json)​

Loads the controls specified in a json representation into the existing container .

ParameterTypeDescription
containerContainerControlContainer to load with the new controls.
jsonStringJSON representation of the container properties and of the controls to create. When null or empty, nothing is loaded.

Returns: ContainerControl. The container instance.

The members of the root object are assigned to the container and the new controls are added to its existing controls. Event handlers can refer to methods declared in the class of the container , including private methods.

Throws:

Example:

Loading a view into a panel:

this.panel1.LoadView(@"{
""controls"": [
{ ""_type"": ""Button"", ""name"": ""buttonSave"", ""text"": ""Save"", ""dock"": ""Bottom"", ""click"": ""buttonSave_Click"" }
]
}");

Static member LoadView(container, jsonStream)​

Loads the controls specified in a jsonStream representation into the existing container .

ParameterTypeDescription
containerContainerControlContainer to load with the new controls.
jsonStreamStreamStream containing the JSON representation of the container properties and of the controls to create. When null, nothing is loaded.

Returns: ContainerControl. The container instance.

The stream is read but not closed.

Throws:

Example:

Loading the layout of a form from a JSON file:

private void Form1_Load(object sender, EventArgs e)
{
using (var stream = File.OpenRead(Application.MapPath("Views/Form1.json")))
{
this.LoadView(stream);
}
}

Static member LoadView(container, model)​

Loads the controls specified in a model representation into the existing container .

ParameterTypeDescription
containerContainerControlContainer to load with the new controls.
modelObjectObject model representation of the container properties and of the controls to create. When null, nothing is loaded.

Returns: ContainerControl. The container instance.

The model is accessed dynamically: every nested object that defines a control must support the string indexer used to read the "_type" member, like DynamicObject or the objects returned by Parse.

Throws:

Example:

Adding a text box to the current form from a DynamicObject model:

dynamic textBox = new DynamicObject();
textBox._type = "TextBox";
textBox.name = "textBoxEmail";
textBox.labelText = "Email:";
textBox.dock = "Top";

dynamic model = new DynamicObject();
model.controls = new object[] { textBox };

this.LoadView((object)model);