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.$;