Help creating custom layout control
Hello,
I followed this tutorial to create a custom layout control: http://www.sitefinity.com/40/help/developer-manual/pages-layouts-creating-layout-controls.html. I am attempting to create a custom tab container and tab layout control. I am doing it as a layout control because I need to be able to drop widget into the tab, such as images and content blocks. I am able to get my layout control to show up in the page edit screen, but I cannot edit it or drag other elements on to it.
I have set up a separate project for my custom controls/layouts. Here is the contents of my tab.cs:
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
Telerik.Sitefinity.Web.UI;
namespace
IDT.Web.SitefinityControls.Layouts.Tabs
public
class
Tab : LayoutControl
public
override
string
Layout
get
return
this
.CustomTemplate;
public
override
string
AssemblyInfo
get
return
GetType().ToString();
set
base
.AssemblyInfo = value;
protected
override
void
CreateChildControls()
base
.CreateChildControls();
public
string
CustomTemplate =
"IDT.Web.SitefinityControls.Layouts.Tabs.Resources.Views.Tab"
;
<%@ Control Language="C#" %>
<
div
id
=
"TabCol"
runat
=
"server"
class
=
"tab sf_cols"
>
<
div
id
=
"TabColOut"
runat
=
"server"
class
=
"sf_colsOut"
>
<
div
id
=
"TabColIn"
runat
=
"server"
class
=
"sf_colsIn"
>
</
div
>
</
div
>
</
div
>
Hello Sean,
Thank you for contacting Telerik Support.
I was able to run your code locally and all it does is to add a 100% column layout, on which I am able to put widgets, but it does not show tabs. Can you please clarify how you wish to create tabs?
All the best,
Boyan Barnev
the Telerik team
My idea for creating tabs was to create a wrapper for the tabstrip from radcontrols, which is included in the distribution. I am planning on having two layout controls, a tab container and individual tabs. Each tab can have any sort of widget dragged onto it.
However, I can't get past just being able to drag content onto my layout control. Also, when I click the edit link, it doesn't pull up the edit overlay.
Hi Sean,
What you need is generally not supported, but I managed to create a working example of tabbed layout control using RadTabStrip and RadMultiPage. I have attached the source file. You must register the control the same way you will register any custom layout control.
You will notice that there are glitches - when you drag the control to a page/template, you will need to refresh the page, before dropping controls on it. Also, my implementation is using predefined tabs. It is certainly not perfect, but you should be able to further extend the control to better suit your needs.
I hope this helps.
Lyubomir,
Thanks for your help. That did work, although I was not able to figure out how to adapt it to my needs.
Instead I am trying to implement tabs as a widget. I am getting the following error:
Server Error in '/Sitefinity' Application.
Object reference not set to an instance of an object.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
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.
Stack Trace:
[NullReferenceException: Object reference not set to an instance of an object.]
Telerik.Web.UI.TabStrip.Rendering.Renderer.AddAttributesToRender(HtmlTextWriter writer) +98
System.Web.UI.WebControls.WebControl.RenderBeginTag(HtmlTextWriter writer) +31
System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) +31
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter writer) +14
System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) +51
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) +47
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.HtmlControls.HtmlTableRow.RenderChildren(HtmlTextWriter writer) +60
System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) +47
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.HtmlControls.HtmlTable.RenderChildren(HtmlTextWriter writer) +60
System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) +47
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
Telerik.Web.UI.RadWebControl.RenderContents(HtmlTextWriter writer) +118
Telerik.Web.UI.RadWebControl.Render(HtmlTextWriter writer) +125
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
Telerik.Web.UI.RadDockZone.RenderChildren(HtmlTextWriter writer) +205
Telerik.Web.UI.RadWebControl.RenderContents(HtmlTextWriter writer) +118
Telerik.Web.UI.RadWebControl.Render(HtmlTextWriter writer) +125
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) +47
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) +47
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) +47
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter writer) +14
System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) +51
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) +47
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.HtmlControls.HtmlTableRow.RenderChildren(HtmlTextWriter writer) +60
System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) +47
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.HtmlControls.HtmlTable.RenderChildren(HtmlTextWriter writer) +60
System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) +47
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
Telerik.Web.UI.RadWebControl.RenderContents(HtmlTextWriter writer) +118
Telerik.Web.UI.RadWebControl.Render(HtmlTextWriter writer) +125
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
Telerik.Web.UI.RadDockZone.RenderChildren(HtmlTextWriter writer) +205
Telerik.Web.UI.RadWebControl.RenderContents(HtmlTextWriter writer) +118
Telerik.Web.UI.RadWebControl.Render(HtmlTextWriter writer) +125
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) +47
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter writer) +14
System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) +51
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.HtmlControls.HtmlForm.RenderChildren(HtmlTextWriter writer) +314
System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) +47
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +245
System.Web.UI.Page.Render(HtmlTextWriter writer) +39
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +11249515
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5273
I have tried to base it mostly off the NewsRotator widget. I think that the offending code is in the TabControl.cs file:
using
System;
using
System.ComponentModel;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Web.UI;
using
System.Web.UI.WebControls;
using
Telerik.Sitefinity;
using
Telerik.Sitefinity.GenericContent.Model;
using
Telerik.Sitefinity.Localization;
using
Telerik.Sitefinity.Modules.News.Web.UI;
using
Telerik.Sitefinity.Modules.Pages.Web.UI;
using
Telerik.Sitefinity.News.Model;
using
Telerik.Sitefinity.Pages.Model;
using
Telerik.Sitefinity.Web.DataResolving;
using
Telerik.Sitefinity.Web.UI;
using
Telerik.Sitefinity.Web.UI.ControlDesign;
using
Telerik.Web.UI;
namespace
IDT.Web.SitefinityControls.Widgets.Tabs
[RequireScriptManager]
[ControlDesigner(
typeof
(TabDesigner)), PropertyEditorTitle(
typeof
(Labels),
"Tab Options"
)]
class
TabControl : SimpleView
private
string
providerName =
"OpenAccessDataProvider"
;
public
string
[] Tabs
get
;
set
;
public
int
SelectedIndex
get
;
set
;
public
int
NumTabs
get
;
set
;
/// <summary>
/// Default template name.
/// </summary>
private
string
layoutTemplateName =
"IDT.Web.SitefinityControls.Widgets.Tabs.Resources.Views.Tabs.ascx"
;
/// <summary>
/// Default design setting.
/// </summary>
private
Tabs.TabDesign tabDesign = TabDesign.HorizontalTop;
public
TabDesign TabDesign
get
return
this
.tabDesign;
set
this
.tabDesign = value;
protected
virtual
RadMultiPage RadMultiPage1
get
return
this
.Container.GetControl<RadMultiPage>(
"RadMultiPage1"
,
true
);
protected
virtual
RadTabStrip RadTabStrip1
get
return
this
.Container.GetControl<RadTabStrip>(
"RadTabStrip1"
,
true
);
public
virtual
string
ProviderName
get
return
this
.providerName;
set
this
.providerName = value;
protected
override
void
InitializeControls(GenericContainer container)
// Nothing here yet.
protected
void
RadTabStrip1_ItemDataBound(
object
sender, RadTabStripEventArgs e)
protected
override
string
LayoutTemplateName
get
return
this
.layoutTemplateName;
//protected override HtmlTextWriterTag TagKey
//
// get
//
// ////Use div wrapper tag to make easier common styling. This will surround the layout template with a div tag.
// return HtmlTextWriterTag.Div;
//
//
Any help would be appreciated.
Thanks,
Sean
Hello Sean,
In your first post you wrote that you need to be able to drag widgets in the tabs. You will not be able to do this with a simple widget, it must be a layout control. Has this requirement changed?
By the way, here's another way to simulate tabbed layout control, using custom master page and jQuery. This approach lets you define content place holders in the master page where you can drop any controls of your liking and wrap them in tabs.
In the master page paste this code:
<
form
id
=
"form1"
runat
=
"server"
>
<
asp:ScriptManager
runat
=
"server"
ID
=
"scriptManager1"
></
asp:ScriptManager
>
<
div
>
<
asp:ContentPlaceHolder
ID
=
"ContentPlaceHolder1"
runat
=
"server"
>
</
asp:ContentPlaceHolder
>
</
div
>
<
script
type
=
"text/javascript"
src
=
"https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"
></
script
>
<
script
type
=
"text/javascript"
src
=
"https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.10/jquery-ui.min.js"
></
script
>
<
script
>
$(function ()
$("#tabs").tabs();
);
</
script
>
<
div
id
=
"tabs"
>
<
ul
>
<
li
><
a
href
=
"#tabs-1"
>News</
a
></
li
>
<
li
><
a
href
=
"#tabs-2"
>Events</
a
></
li
>
</
ul
>
<
div
id
=
"tabs-1"
>
test1
<
asp:ContentPlaceHolder
ID
=
"NewsPlaceholder"
runat
=
"server"
></
asp:ContentPlaceHolder
>
</
div
>
<
div
id
=
"tabs-2"
>
test2
<
asp:ContentPlaceHolder
ID
=
"EventsPlaceHolder"
runat
=
"server"
></
asp:ContentPlaceHolder
>
</
div
>
</
div
>
</
form
>
Lyubomir,
Originally, I was attempting to create a sort of layout/widget hybrid that would allow to to drag any other content types onto the widget. Since then I have abandoned that to try and just create a tab widget that would allow me to at least take advantage of the content editor and allow a site editor to set tab and tab names.
Unfortunately, the solution that you describe in your last post will not work because I need it to be something that a non-developer content editor can set up and use without developer needing to be involved. It looks like what you are describing would work, but that it would require me to create a new tab instance each time they wanted to add something like that.
Thanks!
Sean
Hi Sean,
You are correct, the solution I proposed will not allow the users to add tabs by themselves. Currently I cannot think of a better solution. I will update the thread if I come up with an idea.
Hi Lyubomir
What is the CSS for the master page you've posted before?
We went through this same thought process when 4.x came out. What we ended up doing was to have two layout sections on the page. In one layout, we added generic content to place our ul for the tabs. In the other layout which was out tab pane layout, we added a layout for each control we wanted to feature as a tab pane. Each of these layouts could contain one or more controls.
is the url www.ttha.com ?
Yes it is. Sorry for the typo.
As far as I understand, it's a kind-of-customizable tabbed control. If so, would you consider selling that solution as I'm fed up with the "next-version" story of sitefinity...
This is a rather simple setup. Give me some time to put together an archive and a short video on how to implement this.
Ok, I have created an archive with the files you will need and a short video on implementing the tabs. The control functionality is derived from the tabs plugin found here jQuery Tools. I tweaked this plugin to allow for the jquery UI styling to be used. Originally I thought it was the jQuery UI tabs but after further investigation, we used the jQuery Tools plugin. While you don't actually need the UI interface to run this, I did add it in my demo video. You would only need to use the UI styling to get the look. I am using the smoothness theme from the jQuery UI. As for Sitefinity, I am just using a base 4.4 install, however you can use any of the 4.x versions. If you have a Sitefinity navigation element on the page, you may want to make sure you set the jquery includes to the bottom of the page template. This is a known solution when adding jQuery files to a site that already has jQuery included via the Sitefinity navigation. (Telerik controls)
Hi Richard,
Thank you for sharing this with the community. This is very useful sample . I have updated your Telerik points!
Regards,Richard,
The information and video is very useful. "Telerik Support" should take a lesson from what you've done ;)
Thank you very much!
Hi Richard
I have tried to adapt your video to my site but I guess I'm missing something. I have recorded what I've done here (cannot upload since it's 8MB). Can you help?
(I have put js and css folders in root directory of my site as in your video. However, my site uses a custom template under App_Data\Sitefinity\... I'm not sure if can cause that problem?)
Murat,
From the video, the only thing I can think of is the jquery.tabs.js file is not being instantiated. This could be a cause of the menu that you already have on a base page template. When you run the page, are you getting any javascript errors? If so, can you let me know what the error is? Maybe try using Google Chrome if IE is not giving you more precise error information.
Hi Richard
If it's not too much to ask, I can let you access everything on that host. Can you contact me thru skype? my account name is meraydin.
I just sent you an invite on Skype. richard.graydigitalgroup
In helping Murat out today, I realized that my jquery.tabs.js file is a newer file and the code snippet to instantiate the plugin is using the wrong plugin name. Here is the corrected code snippet to use to instantiate the control.
jQuery(document).ready(funciton()
// setup ul.tabs to work as tabs for each div under the div.tabPanes element
jQuery(
".ui-tabs ul"
).tabs(
"div.tabPanes div.pane"
);
);
if
(
typeof
($telerik.$) ===
"undefined"
)
if
(
typeof
(jQuery) !==
"undefined"
)
$telerik.$ = jQuery.noConflict(
true
);
if
(
typeof
($) !==
"undefined"
)
$telerik.$ = $.noConflict(
true
);
var
jQuery = window.jQuery = window.$ = $telerik.$;