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.
- C#
- VB.NET
public static class ViewBuilder
Public 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
| Name | Type | Description | Value |
|---|---|---|---|
| ResolveEventHandler | Func<Object, EventDescriptor, String, MethodInfo> | Resolves the value in name to a MethodInfo that can be attached to the event defined as descriptor . | |
| ResolveReference | Func<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
Create(json)
Creates a new ContainerControl from the specified json representation.
| Parameter | Type | Description |
|---|---|---|
| json | String | 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 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:
- ArgumentNullException json is null.
- Exception The "_type" member is missing or the type cannot be resolved.
- ArgumentException A property cannot be assigned.
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();
Create(json)
Creates a new ContainerControl from the JSON representation read from the specified json stream.
| Parameter | Type | Description |
|---|---|---|
| json | Stream | Stream 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:
- ArgumentNullException json is null.
- Exception The "_type" member is missing or the type cannot be resolved.
- ArgumentException A property cannot be assigned.
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();
}
Create(model)
Creates a new ContainerControl from the specified model representation.
| Parameter | Type | Description |
|---|---|---|
| model | Object | Object 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:
- ArgumentNullException model is null.
- Exception The "_type" member is missing or the type cannot be resolved.
- ArgumentException A property cannot be assigned.
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();
LoadView(container, json)
Loads the controls specified in a json representation into the existing container .
| Parameter | Type | Description |
|---|---|---|
| container | ContainerControl | Container to load with the new controls. |
| json | String | JSON 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:
- ArgumentNullException container is null.
- Exception The "_type" member of a child object is missing or the type cannot be resolved.
- ArgumentException A property cannot be assigned.
Example:
Loading a view into a panel:
this.panel1.LoadView(@"{
""controls"": [
{ ""_type"": ""Button"", ""name"": ""buttonSave"", ""text"": ""Save"", ""dock"": ""Bottom"", ""click"": ""buttonSave_Click"" }
]
}");
LoadView(container, jsonStream)
Loads the controls specified in a jsonStream representation into the existing container .
| Parameter | Type | Description |
|---|---|---|
| container | ContainerControl | Container to load with the new controls. |
| jsonStream | Stream | Stream 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:
- ArgumentNullException container is null.
- Exception The "_type" member of a child object is missing or the type cannot be resolved.
- ArgumentException A property cannot be assigned.
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);
}
}
LoadView(container, model)
Loads the controls specified in a model representation into the existing container .
| Parameter | Type | Description |
|---|---|---|
| container | ContainerControl | Container to load with the new controls. |
| model | Object | Object 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:
- ArgumentNullException container is null.
- Exception The "_type" member of a child object is missing or the type cannot be resolved.
- ArgumentException A property cannot be assigned.
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);