Custom Control Designer for Usercontrol
Is it possible to use a control designer with a user control in Sitefinity 4? I only see examples of control designers used with custom controls. (I realize that the control designer itself must be a custom control).
Hi Jeff,
You need a custom control. Here is a tutorial that you can use.
Greetings,
Ivan Dimitrov
the Telerik team
I was able to follow that tutorial to create a control designer for a custom control, however I am interested in knowing if there is a way to create a control designer for a user control, as I have done in the past with Sitefinity 3.7. The control designer, providing the user friendly configuration would a custom control, but the actual widget would be a user control widget.
Hi Jeff Dease,
This can be done in 4.0 as well. You just need to decorate your user control class with the ControlDesigner attribute.
Kind regards,
Radoslav Georgiev
the Telerik team
Hi Jeff Dease,
I have attached dummy classes to get you started on the control. You need to add the content of the archive in the root of the SitefinityWebApp project. Set the .ascx file and .js file of the control designer to be built as embedded resource and add the bellow line in the AssemblyInfo.cs file in Properties folder:
[assembly: WebResource(
"SitefinityWebApp.Controls.UserControlDesigner.js"
,
"text/javascript"
)]
Hi Radoslav,
How do i make the two fiels you as embedded resources in the sitefinity web project? I dont have the Assembly.cs file for the web project unlike a class library. Do I have to create one at root level?
Thanks,
Duneel
Hi Radoslav,
I'm following along in this example using the controls.zip file and also looking at the Creating a Custom Control Designer tutorial from your documentation, and I'm running into a javascript error. Even with one field, implementing either:
var data = this._propertyEditor().get_control();
in the refreshUI area of the prototype,
or
var controlData = this._propertyEditor().get_control();
in the applyChanges area of the prototype
is giving me an "Error:function expected" at each of those two lines. Any idea what might be causing that? It happens regardless of whether I try the controls.zip example or follow the example in the tutorial with a custom control. Always that error.
Thanks
- William
Hi Jeff,
Can you post the entire js code, the code of the control designer and the code of your custom control.
All the best,
Ivan Dimitrov
the Telerik team
Hi Radoslav,
I have implemented a custom designer containing ContentBlock for a user control. When I tried to access the edit properties of the control i'm getting an error in the XXXXDesigner.js file. It seems the _contentBlockControl is null and both refreshUI and applyChanges functions fails. My Control Desiger code placed in a folder named "CertifiedAgents" under the class library called "ControlDesigners". That's whay the namespace is "ControlDesigners.CertifiedAgents". Please see the code below.... I'm stuck at this point as I dont know why ._contentBlockControlTop is null in the .js file.
Designer.cs
public override IEnumerable<
ScriptDescriptor
> GetScriptDescriptors()
var scriptDescriptors = new List<
ScriptDescriptor
>(base.GetScriptDescriptors());
var desc = (ScriptControlDescriptor)scriptDescriptors.Last();
var contentBlockControlTop = this.ContentBlockTop;
desc.AddComponentProperty("contentBlockControlTop", contentBlockControlTop.ClientID);
return scriptDescriptors.ToArray();
protected virtual ContentBlock ContentBlockTop
get
return this.Container.GetControl<
ContentBlock
>("ContentBlock1", true);
Type.registerNamespace("ControlDesigners.CertifiedAgents");
ControlDesigners.CertifiedAgents.CertifiedAgentsDesigner = function (element)
// element
this._contentBlockControlTop = null;
ControlDesigners.CertifiedAgents.CertifiedAgentsDesigner.initializeBase(this, [element]);
ControlDesigners.CertifiedAgents.CertifiedAgentsDesigner.prototype =
initialize: function ()
ControlDesigners.CertifiedAgents.CertifiedAgentsDesigner.callBaseMethod(this, 'initialize');
,
dispose: function ()
ControlDesigners.CertifiedAgents.CertifiedAgentsDesigner.callBaseMethod(this, 'dispose');
,
get_contentBlockControlTop: function ()
return this._contentBlockControlTop;
,
set_contentBlockControlTop: function (value)
this._contentBlockControlTop = value;
,
/* ----------------------------- public methods ----------------------------- */
//refreshes the UI overrides the base interface
refreshUI: function ()
this._refreshMode = true;
var data = this.get_controlData();
this.get_contentBlockControlTop().set_html(data.ContentTop)
,
// forces the designer to apply the changes on UI to the cotnrol Data buth
applyChanges: function ()
var data = this.get_controlData();
data.ContentTop = this.get_contentBlockControlTop().get_html();
ControlDesigners.CertifiedAgents.CertifiedAgentsDesigner.registerClass('ControlDesigners.CertifiedAgents.CertifiedAgentsDesigner', Telerik.Sitefinity.Web.UI.ControlDesign.ControlDesignerBase);
if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
<%@ Control Language="C#"%>
<%@ Register Assembly="Telerik.Sitefinity.Modules.GenericContent.Web.UI" Namespace="Telerik.Sitefinity.Modules.GenericContent.Web.UI" TagPrefix="telerik" %>
<
strong
>Content Top:</
strong
>
<
telerik:ContentBlock
runat
=
"server"
ID
=
"ContentBlock1"
></
telerik:ContentBlock
>
Hi Radoslav,
Here's what I did.... I replaced the ContentBlock with RadEditor in the designer.cs and in template.ascx and the same javascript code works perfectly fine. And looks like the above null issue is happenning when it has ContentBlock instead of a RadEditor. Do I have to change the implementation of the .js file and the designer.cs file if it is having a ContentBlock?
When I have the RedEditor in place, when I go to the edit pannel of my widget I'm getting series of errors (attached) and when I hit OK and continue it brings up the edit dialog with the RadEditor and I can save my content successfully. This happens ONLY in the first time when I go to edit properties of the newly placed widget. Any idea why??
Thanks,
Duneel
Hello Duneel,
The problem you are experiencing is because the ContentBlock control used is the whole control, not only its designer. You can try the approach similar to the one in this forum thread. You can use the same markup as the one used in the custom designer of the content block sampled in this thread.
Greetings,
Radoslav Georgiev
the Telerik team
Hi Radoslav,
I changed my custom control designer to use the ContentBlock as explained in the other blog post you sent me. however now i have problems reading the entered content. I've posted a question in the same post about this. Appriciate if you too can input some ideas.
Thanks!
Duneel
Hi Jeff,
OK, we will check the other post and keep the discussion there.
Regards,
Ivan Dimitrov
the Telerik team
Hi William:
I did not see an answer to your post, but I also had this same problem. There is a bug in the sample documentation.
The statement
var data = this._propertyEditor().get_control();
should read:
var data = this._propertyEditor.get_control();
_propertyEditor is a field, not a method.
Thanks, Rick.
I'd meant to post an update to this as I too found that code typo. Just didn't get back to it.
I do appreciate the response, though.
- William
Hello,
The PropertyEditor represents dialog control for editing control properties.It gets or sets the reference to the parent property editor control when you have more than one view in the control designer ( for instance NewsControlDesginer)
get_propertyEditor()
You can use this property to get the instance of the parent object, called “PropertyEditor”. This object holds references to both designer and property grid. Generally you don’t need to use this property.
- set_propertyEditor()
Used by Sitefinity; do not use.
Greetings,
Ivan Dimitrov
the Telerik team
Ivan,
I am getting this error when attempting to edit the User Control.
An unhandled exception was generated during the execution of the
current web request. Information regarding the origin and location of the
exception can be identified using the exception stack trace below.
|
|
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Resources;
using System.Web.UI;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SitefinityWebApp")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Telerik")]
[assembly: AssemblyProduct("Telerik Sitefinity CMS")]
[assembly: AssemblyCopyright("Copyright © Telerik 2010")]
[assembly: AssemblyTrademark("Sitefinity")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
[assembly: System.Security.SecurityRules(System.Security.SecurityRuleSet.Level1)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("3d5900ae-111a-45be-96b3-d9e4606ca793")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.0.1098.0")]
[assembly: AssemblyFileVersion("4.0.1098.0")]
[assembly: NeutralResourcesLanguageAttribute("en")]
[assembly: WebResource("SitefinityWebApp.Controls.AspButtonDesigner.js", "text/javascript")]
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="AspButton.ascx.cs" Inherits="SitefinityWebApp.Controls.AspButton" %>
<
asp:Button
ID
=
"aspButton"
runat
=
"server"
Text
=
"Button"
/>
using System;
using Telerik.Sitefinity.Web.UI.ControlDesign;
namespace SitefinityWebApp.Controls
[ControlDesigner(typeof(AspButtonDesigner))]
public partial class AspButton : System.Web.UI.UserControl
private string _text = "Button";
public string Text
get return _text;
set _text = value;
private string _selectedPage;
public string SelectedPage
get
if (this._selectedPage == null)
return string.Empty;
return this._selectedPage;
set this._selectedPage = value;
protected void Page_Load(object sender, EventArgs e)
this.aspButton.PostBackUrl = _selectedPage;
this.aspButton.Text = _text;
using System;
using Telerik.Sitefinity.Web.UI.ControlDesign;
using Telerik.Sitefinity.Web.UI;
using System.Web.UI;
using Telerik.Web.UI;
using System.Web.UI.WebControls;
using Telerik.Sitefinity.Pages.Model;
using System.Collections.Generic;
namespace SitefinityWebApp.Controls
public class AspButtonDesigner : ControlDesignerBase
/// <
summary
>
/// Gets the name of the embedded layout template.
/// </
summary
>
/// <
value
></
value
>
/// <
remarks
>
/// Override this property to change the embedded template to be used with the dialog
/// </
remarks
>
protected override string LayoutTemplateName
get
return "SitefinityWebApp.Controls.AspButtonDesigner.ascx";
/// <
summary
>
/// Gets a reference to the blog post select button
/// </
summary
>
protected LinkButton PageSelectButton
get
return Container.GetControl<
LinkButton
>("pageSelectButton", true);
/// <
summary
>
/// Gets a reference to the page selector
/// </
summary
>
protected ContentSelector PageSelector
get
return Container.GetControl<
ContentSelector
>("selector", true);
/// <
summary
>
/// Gets the correct instance of the RadWindowManager class
/// </
summary
>
protected virtual RadWindowManager RadWindowManager
get
return this.Container.GetControl<
RadWindowManager
>("windowManager", true);
public override IEnumerable<
ScriptReference
> GetScriptReferences()
var res = new List<
ScriptReference
>(base.GetScriptReferences());
var assemblyName = this.GetType().Assembly.GetName().ToString();
res.Add(new ScriptReference("SitefinityWebApp.Controls.AspButtonDesigner.js", assemblyName));
return res.ToArray();
/// <
summary
>
/// Gets a collection of script descriptors that represent ECMAScript (JavaScript) client components.
/// </
summary
>
/// <
returns
>
/// An <
see
cref
=
"T:System.Collections.IEnumerable"
/> collection of <
see
cref
=
"T:System.Web.UI.ScriptDescriptor"
/> objects.
/// </
returns
>
public override IEnumerable<
ScriptDescriptor
> GetScriptDescriptors()
ScriptControlDescriptor desc = new ScriptControlDescriptor(this.GetType().FullName, this.ClientID);
desc.AddElementProperty("pageSelectButton", this.PageSelectButton.ClientID);
desc.AddComponentProperty("pageSelector", this.PageSelector.ClientID);
desc.AddComponentProperty("radWindowManager", this.RadWindowManager.ClientID);
return new[] desc ;
/// <
summary
>
/// Initializes the controls.
/// </
summary
>
/// <
param
name
=
"container"
>The control container.</
param
>
/// <
remarks
>
/// Initialize your controls in this method. Do not override CreateChildControls method.
/// </
remarks
>
protected override void InitializeControls(GenericContainer container)
this.DesignerMode = ControlDesignerModes.Simple;
this.PageSelector.ServiceUrl = "~/Sitefinity/Services/Pages/PagesService.svc/";
this.PageSelector.ItemType = typeof(Page).FullName;
<%@ Control Language="C#" %>
<%@ Register Assembly="Telerik.Sitefinity" TagPrefix="designers" Namespace="Telerik.Sitefinity.Web.UI.ControlDesign" %>
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
<
telerik:RadWindowManager
ID
=
"windowManager"
runat
=
"server"
Height
=
"100%"
Width
=
"100%"
Behaviors
=
"None"
Skin
=
"Sitefinity"
ShowContentDuringLoad
=
"false"
VisibleStatusBar
=
"false"
>
<
Windows
>
<
telerik:RadWindow
ID
=
"widgetEditorDialog"
runat
=
"server"
Height
=
"100"
Width
=
"100"
ReloadOnShow
=
"true"
Behaviors
=
"Close"
Modal
=
"true"
/>
</
Windows
>
</
telerik:RadWindowManager
>
<
div
id
=
"selectorTag"
style
=
"display: none;"
class
=
"sfDesignerSelector"
>
<
designers:ContentSelector
ID
=
"selector"
runat
=
"server"
WorkMode
=
"List"
TitleText
=
"Button"
BindOnLoad
=
"false"
SearchBoxInnerText
=
""
SearchBoxTitleText
=
"Narrow by typing post title"
AllowMultipleSelection
=
"false"
/>
</
div
>
<
div
>
<!-- Button Text -->
<
label
for
=
"btnText"
class
=
"sfTxtLbl"
>Page URL</
label
>
<
input
type
=
"text"
id
=
"btnText"
class
=
"sfTxt"
/>
<!-- Page Url -->
<
label
for
=
"selectedPage"
class
=
"sfTxtLbl"
>Page Url</
label
>
<
input
type
=
"text"
id
=
"selectedPage"
class
=
"sfTxt"
/>
<
input
type
=
"hidden"
id
=
"selectedPageId"
/>
<
asp:LinkButton
runat
=
"server"
ID
=
"pageSelectButton"
OnClientClick
=
"return false;"
CssClass
=
"sfLinkBtnIn"
>Select page</
asp:LinkButton
>
</
div
>
Type.registerNamespace("SitefinityWebApp.Controls");
SitefinityWebApp.Controls.AspButtonDesigner = function (element)
SitefinityWebApp.Controls.AspButtonDesigner.initializeBase(this, [element]);
this._parentDesigner = null;
this._pageSelectButton = null;
this._pageSelector = null;
this._radWindowManager = null;
this._showPageSelectorDelegate = null;
this._pageSelectedDelegate = null;
SitefinityWebApp.Controls.AspButtonDesigner.prototype =
/* --------------------------------- set up and tear down --------------------------------- */
initialize: function ()
SitefinityWebApp.Controls.AspButtonDesigner.callBaseMethod(this, 'initialize');
this._toogleGroupSettingsDelegate = Function.createDelegate(this, function ()
dialogBase.resizeToContent(); );
this._showPageSelectorDelegate = Function.createDelegate(this, this._showPageSelector);
$addHandler(this._pageSelectButton, "click", this._showPageSelectorDelegate);
this._pageSelectedDelegate = Function.createDelegate(this, this.pageSelectedDelegate);
this._pageSelector.add_doneClientSelection(this._pageSelectedDelegate);
,
dispose: function ()
SitefinityWebApp.Controls.AspButtonDesigner.callBaseMethod(this, 'dispose');
,
/* --------------------------------- public methods --------------------------------- */
// implementation of IControlDesigner: Forces the control to refersh from the control Data
refreshUI: function ()
var data = this.get_controlData();
jQuery("#selectedPageId").val(controlData.SelectedPage)
,
// implementation of IControlDesigner: forces the designer view to apply the changes on UI to the control Data
applyChanges: function ()
var controlData = this.get_controlData();
controlData.SelectedPage = jQuery("#selectedPageId").val();
,
get_controlData: function ()
var parent = this.get_parentDesigner();
if (parent)
var pe = parent.get_propertyEditor();
if (pe) return pe.get_control();
alert('Control designer cannot find the control properties object!');
,
/* --------------------------------- event handlers --------------------------------- */
// this is an event handler for page selected event
pageSelectedDelegate: function (items)
jQuery(this.get_element()).find('#selectorTag').hide();
if (items == null) return;
var selectedItems = this.get_pageSelector().getSelectedItems();
if (selectedItems != null)
if (selectedItems.length > 0)
jQuery("#selectedPage").val(selectedItems[0].Title)
jQuery("#selectedPageId").val(selectedItems[0].Id)
dialogBase.resizeToContent();
,
_showPageSelector: function ()
var filterItems = [];
var filter = filterItems.join("OR");
this.get_pageSelector().set_itemsFilter(filter);
this.get_pageSelector().dataBind();
jQuery(this.get_element()).find('#selectorTag').show();
dialogBase.resizeToContent();
,
/* --------------------------------- private methods --------------------------------- */
/* --------------------------------- properties --------------------------------- */
// gets the reference to the parent designer control
get_parentDesigner: function () return this._parentDesigner; ,
// sets the reference fo the parent designer control
set_parentDesigner: function (value) this._parentDesigner = value;,
// gets the reference to the propertyEditor control
get_propertyEditor: function () return this._propertyEditor; ,
// sets the reference fo the propertyEditor control
set_propertyEditor: function (value) this._propertyEditor = value; ,
// get the reference to the button that opens page selector
get_pageSelectButton: function () return this._pageSelectButton; ,
// sets the reference to the button that opens page selector
set_pageSelectButton: function (value) this._pageSelectButton = value; ,
// gets the reference to the page selector used to choose a page for showing the detail mode
get_pageSelector: function () return this._pageSelector; ,
// sets the reference to the page selector used to choose a page for showing the detail mode
set_pageSelector: function (value) this._pageSelector = value; ,
get_radWindowManager: function () return this._radWindowManager; ,
set_radWindowManager: function (value)
if (this._radWindowManager != value) this._radWindowManager = value;
SitefinityWebApp.Controls.AspButtonDesigner.registerClass('SitefinityWebApp.Controls.AspButtonDesigner', Sys.UI.Control, Telerik.Sitefinity.Web.UI.ControlDesign.ControlDesignerBase);
if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
Hi
I've used the source code provided here from the archive. Any idea why I get in the JS file at line
SitefinityWebApp.Controls.UserControlDesigner.registerClass('SitefinityWebApp.Controls.UserControlDesigner', Telerik.Sitefinity.Web.UI.ControlDesign.ControlDesignerBase);
the following error:
Object doesn't support this property or method
Telerik.Web.UI.WebResource.axd?_TSM_HiddenField_=ctl01_TSM&compress=1&_TSM_CombinedScripts_=%3b%3bSystem.Web.Extensions%2c+Version%3d4.0.0.0%2c+Culture%3dneutral%2c+PublicKeyToken%3d31bf3856ad364e35%3aen-US%3a8f393b2b-3315-402f-b504-cd6d2db001f6%3aea597d4b%3ab25378d2%3bTelerik.Sitefinity.Resources%3aen-US%3a3dfc1080-eaf3-458e-bf48-a065bc9fddc9%3a5fd29111%3a7ee0bb1f%3a83eb063b%3a64dcfe0a%3a1154458f%3a2232f901%3a24e33f3%3bTelerik.Sitefinity%3aen-US%3a03576c61-1acc-46c1-bbde-96f24ca1c910%3a993d8e92%3a5b182b17%3afa91e8b7%3afe4b1370%3ad0257175%3bTelerik.Web.UI%2c+Version%3d2010.3.1109.40%2c+Culture%3dneutral%2c+PublicKeyToken%3d121fae78165ba3d4%3aen-US%3a6955197e-6bcc-48a0-9bff-1fd043726dc6%3a16e4e7cd%3a6a6d718d%3bTelerik.Sitefinity%2c+Version%3d4.0.1098.0%2c+Culture%3dneutral%2c+PublicKeyToken%3db28c218413bdf563%3aen-US%3a03576c61-1acc-46c1-bbde-96f24ca1c910%3aa67f29d6%3a798214d1%3bSitefinityWebApp%2c+Version%3d4.0.1098.0%2c+Culture%3dneutral%2c+PublicKeyToken%3dnull%3aen-US%3ad76b1205-6d6c-4cd6-abff-373798ab9541%3acffcdff%3bTelerik.Sitefinity%2c+Version%3d4.0.1098.0%2c+Culture%3dneutral%2c+PublicKeyToken%3db28c218413bdf563%3aen-US%3a03576c61-1acc-46c1-bbde-96f24ca1c910%3a29ad74ff%3a5053a0f8%3bTelerik.Web.UI%2c+Version%3d2010.3.1109.40%2c+Culture%3dneutral%2c+PublicKeyToken%3d121fae78165ba3d4%3aen-US%3a6955197e-6bcc-48a0-9bff-1fd043726dc6%3af7645509%3a24ee1bba%3a1e771326%3aa7e79140%3bTelerik.Sitefinity%2c+Version%3d4.0.1098.0%2c+Culture%3dneutral%2c+PublicKeyToken%3db28c218413bdf563%3aen-US%3a03576c61-1acc-46c1-bbde-96f24ca1c910%3aee25fa49%3bTelerik.Sitefinity.Resources%2c+Version%3d4.0.1098.0%2c+Culture%3dneutral%2c+PublicKeyToken%3dnull%3aen-US%3a3dfc1080-eaf3-458e-bf48-a065bc9fddc9%3a1077b7cd%3bTelerik.Sitefinity%2c+Version%3d4.0.1098.0%2c+Culture%3dneutral%2c+PublicKeyToken%3db28c218413bdf563%3aen-US%3a03576c61-1acc-46c1-bbde-96f24ca1c910%3a4a73a146%3a5c2616b0,
line 6160 character 1
Sorry for the duplicate post but I need to finish something and I can't get past this error.
Regards,
Alex
Hello Alex,
Can you please make sure that you have set the JavaScript file to be built as embedded resource?
Greetings,
Radoslav Georgiev
the Telerik team
Hello Radoslav ,
The embedded resource is selected also for the js and ascx.
I have no clue what could be the cause of this.
Regards,
Alex
Hello Alex,
I am not quite sure what is going on either. Can you please open up a ticket and send me the project. I will debug it locally and see why the error is thrown.
Regards,
Radoslav Georgiev
the Telerik team
Hello Radoslav,
Thanks for your kind intention, but fortunately it works now.
I've deleted the files and created everything from scratch. second time. + iis reset(don't know if relevant).
The error doesn't appear anymore and the control seams to work.
Regards,
Alex
Andrei,
Did you ever get this to work? If so, what was the solution?
Thanks,
Hi,
Did anyone ever get this working in the end,
If so is there any chance you would post it
Thanks