Creating a view
Creating a custom control
The backbone of the view is a custom control. The custom control can reside either in the project of the targeted control or in a separate project. To create the class for the view, perform the following.
-
Add a new class to the project of the control that the designer will be applied to.
For example, name it DesignerView1.
-
Add a reference to the Telerik.Sitefinity assembly.
-
From the context menu of the project, click Add Reference...
-
In the Browse tab, navigate to the folder C:\Program Files (x86)\Telerik\Sitefinity 4.0\Libraries.
-
Select the assembly and click OK.
-
Add a reference to the System.Web.Extensions assembly.
-
From the context menu of the project, click Add Reference...
-
In the .NET tab, select the assembly and click OK.
- Add the using Telerik.Sitefinity.Web.UI.ControlDesign; statement to the DesignerView1 class.
-
Make the DesignerView1 class inherit the ContentViewDesignerView class.
public class DesignerView1 : ContentViewDesignerView { }
Creating a template
The template contains the UI of the view. It is represented by an .ascx file built as an embedded resource. To create a template, perform the following:
-
Add an empty .ascx file to the project structure of the control you want to apply the designer to.
For example, you can place it under Resources/Views/ folder. Name it DesignerView1, to match the name of the view.
- From the context menu of the .ascx file, click Properties.
- In the Properties pane set the BuildAction field to EmbeddedResource.
-
Open the .ascx file and create the UI for the view.
Following is an example of a template that contains a single field for Title.
<div>
<span>Title:</span><br />
<input type="text" id="txtTitle" />
</div>
Implementing the ContentViewDesignerView class
To implement the ContentViewDesignerView class in your view, you must override the following members:
-
InitializeControls
In this override you can access the elements of the template via the container argument.
-
LayoutTemplateName
This property must return the name of the template of the view.
-
GetScriptReferences
In this method, the script for the client component is referenced.
-
GetScriptDescriptors
In this method you can define an instance of your client class and set the desired properties to it.
-
ViewTitle
This property must return the display name of the view.
-
ViewName
This property must return the programmatic name of the view.
Following is the code for the DesignerView1 class:
public class DesignerView1 : ContentViewDesignerView
{
public override string ViewTitle
{
get
{
return "My View";
}
}
public override string ViewName
{
get
{
return this.GetType().Name;
}
}
public override IEnumerable<System.Web.UI.ScriptDescriptor> GetScriptDescriptors()
{
return null;
}
public override IEnumerable<System.Web.UI.ScriptReference> GetScriptReferences()
{
return null;
}
protected override void InitializeControls(Telerik.Sitefinity.Web.UI.GenericContainer container)
{
}
protected override string LayoutTemplateName
{
get
{
return string.Empty;
}
}
}
Referencing the template
To wire up the template with the view, you must return its name via the LayoutTemplateName property. It specifies the path to the embedded resource following the naming convention <Namespace>.<ResourceFolderPath>.<TemplateName>, where you must replace path slashes inside the resource folder path with dots. For example, if you have project called NewsRotator and the path to the template file is Resources/Views/DesignerView1.ascx, the LayoutTemplateName property must return the following:
protected override string LayoutTemplateName
{
get
{
return "NewsRotator.Resources.Views.DesignerView1.ascx";
}
}
Implementing the client component
You must store the client class in a .js file in the project, where the view resides. To implement the client component, you must do the following:
-
Add a new .js to the project of your view.
You can name the file the same way as the view. For example, if the class is named DesignerView1, name the file DesignerView1.js.
- From the context menu of the .js file, click Properties.
- In the Properties pane set the BuildAction field to EmbeddedResource.
- Open the .js file.
-
In the .js file, create the namespace for the client code.
This is done by calling the registerNamespace of the Type class.
Type.registerNamespace("NewsRotator");
NOTE: The same namespace must be used throughout the entire client code in this file.
-
Define the client class in the following way:
NewsRotator.DesignerView1 = function (element) {
NewsRotator.DesignerView1.initializeBase(this, [element]);
}
-
Define the prototype for the class. It must include the following methods:
-
initialize
This method is called when an instance of the class is created. In it, you must call the initialize method of the ControlDesignerBase class.
-
dispose
This method is called when the instance of the class is no longer used. In it, you must call the dispose method of the ControlDesignerBase class.
-
refreshUI
This method is called when the view is opened. In it you must get an instance of the control and populate the UI with the values of the properties of the control.
-
applyChanges
This method is called when the changes must be applied to the control. In it you must get an instance of the control and set its properties to the new values in the UI.
-
set_parentDesigner
This method is used by the IDesignerViewControl interface for passing an instance of the designer to the view. Via this instance the view can access the data of the control.
NewsRotator.DesignerView1.prototype = {
initialize: function () {
NewsRotator.DesignerView1.callBaseMethod(this, 'initialize');
},
dispose: function () {
NewsRotator.DesignerView1.callBaseMethod(this, 'dispose');
},
refreshUI: function () {
var controlData = this.get_controlData();
jQuery("#txtTitle").val(controlData.Title);
},
applyChanges: function () {
var controlData = this.get_controlData();
controlData.Title = jQuery("#txtTitle").val();
},
get_controlData: function () {
return this.get_parentDesigner().get_propertyEditor().get_control();
},
get_parentDesigner: function () {
return this._parentDesigner;
},
set_parentDesigner: function (value) {
this._parentDesigner = value;
}
}
-
Register the client class and specify its base class.
You do this by calling the registerClass method. You must pass the System.UI.Control as the base class and specify that the IDesignerViewControl interface is implemented.
NewsRotator.DesignerView1.registerClass('NewsRotator.DesignerView1', Sys.UI.Control, Telerik.Sitefinity.Web.UI.ControlDesign.IDesignerViewControl);
if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
Referencing the client script
You must reference the client component from the view class. You do this in the override for the GetScriptReference method. In it you must create a script reference for your client component. When creating the reference, you must specify the name of the embedded resource that contains the client component and the assembly it resides in. The name of the resource follows the same naming conventions as the name of the template.
public override IEnumerable<System.Web.UI.ScriptReference> GetScriptReferences()
{
var res = new List<System.Web.UI.ScriptReference>();
var assemblyName = this.GetType().Assembly.GetName().ToString();
res.Add(new System.Web.UI.ScriptReference("NewsRotator.Resources.DesignerView1.js", assemblyName));
return res.ToArray();
}
You must specify a script descriptor for the view. This is done in the GetScriptDescriptors override.
public override IEnumerable<System.Web.UI.ScriptDescriptor> GetScriptDescriptors()
{
var descriptor = new ScriptControlDescriptor(this.GetType().FullName, this.ClientID);
return new[] { descriptor };
}