More in this section

Forums / General Discussions / Custom Control with Custom Template / Resources (if available)

Custom Control with Custom Template / Resources (if available)

3 posts, 1 answered
  1. Daniel
    Daniel avatar
    35 posts
    Registered:
    15 Jun 2010
    20 Oct 2010
    Link to this post
    Greetings,

    I have my own Custom Controls each with their own embedded Templates and Resource files (.ascx, .css). What I need to do is that if there's a Custom Template available inside the ControlTemplates folder of the current Template in use by the page that hosts the Custom Control then have the control use that one instead of the embedded one. Also trying to achieve this for CSS files as well.

    For example, using a Custom Control named Test, I would override the LayoutTemplatePath of the Control and check if the file 'App_Data/Sitefinity/WebsiteTemplates/<Current Template>/ControlTemplates/Teste.ascx' existed and if so, return it, otherwise return null, making the control use the LayoutTemplate instead of the LayoutTemplatePath which would cause him to use the embedded .ascx template file.

    Is there a way on code-behind to get the current Page Template directory?

    I would also need a way to include an external CSS file, if available, otherwise use the embedded one. 

    For example, on the InitializeControls method I could verify if the file 'App_Data/Sitefinity/WebsiteTemplates/<Current Template>/App_Themes/<Current Theme>/Styles/Test.css' and if so, then include it on the ResourceLinks present on the Custom Control, otherwise include the embedded one.

    Is there a way on code-behind to obtain the current Page Theme directory?

    Also, is this the correct procedure of achieving this (load external resources, css, ascx, images, if they are available, otherwise load the embedded ones) or is there a more convenient way that I'm missing?

    Thanks in advance,
    Daniel
  2. Radoslav Georgiev
    Radoslav Georgiev avatar
    3370 posts
    Registered:
    01 Feb 2016
    26 Oct 2010
    Link to this post
    Hi Daniel,

    Thank you for using our services.

    Unfortunately such functionality does not come out of the box with Sitefinity and your idea of implementing this seems like the most convenient. The problem however is that you would have to override each control you want to achieve this for. For example you would need to override the news view control and get the current page. From the current page you can extract its template path and theme name:
    protected override void CreateChildControls()
    {
        SiteMapNode currentNode = SiteMapBase.GetCurrentProvider().CurrentNode;
        PageSiteNode node = (PageSiteNode)currentNode;
        PageNode page;
        if (node != null)
        {
            page = App.WorkWith().Pages().Where(p => p.UrlName == node.UrlName).Get().First();
            string masterPage = page.Page.Template.MasterPage;
            string theme = page.Page.Template.Theme;
            PageManager manager = PageManager.GetManager();
        }
        this.MasterViewDefinition.TemplatePath = "~/App_Data/Sitefinity/WebsiteTemplates/DefaultTemplate/ControlTemplates/News/ListView.ascx";
        base.CreateChildControls();
    }


    Regards,
    Radoslav Georgiev
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
    Answered
  3. Daniel
    Daniel avatar
    35 posts
    Registered:
    15 Jun 2010
    26 Oct 2010
    Link to this post
    Greetings,

    I've sorted this out using the following solution:

    First I still keep an embedded .ascx for each of my custom controls with the required controls on it but without styling.

    Secondly I create an external .ascx for them with a ResourceFile pointing to the external .css file, this works since then the resourcemanager will make use of the current theme directory to locate that file. It's basically a fallback system, the external .ascx with the required .css and images should actually be theme-dependent and as such only the external ones should be styled. At least this is how I consider it working good for me. If an external view ain't found then it uses an internal one which still provides functionality without any styling (although you could also include embedded styling if you wanted).

    Then I also created a CustomSimpleView class which extends the SimpleView since I wanted to hide most of the properties from the Advanced Designer. On this class I overrided the LayoutTemplatePath to the following:

    [Browsable(false)]
            public override string LayoutTemplatePath
            {
                get
                {
                     if (Page.Master == null)
                     {
                         return null;
                     }

                     var customTemplateFile = String.Format("{0}ControlTemplates/{1}.ascx", Page.Master.AppRelativeVirtualPath.Substring(0, Page.Master.AppRelativeVirtualPath.IndexOf("App_Master")), ResourcesAssemblyInfo.Name);

     
                    return File.Exists(HttpContext.Current.Server.MapPath(customTemplateFile)) ? customTemplateFile : null;
                }
            }

    All my Custom Controls implement this CustomSimpleView and as such if a Template named 'ControlClassName.ascx' is found it uses it, otherwise the LayoutTemplatePath returns null making the control use the LayoutTemplateName instead which points to the embedded .ascx file. There's a few Custom Controls where I use several views in which the active one will vary depending on a configured designer property. In this case I just override this LayoutTemplatePath property in the control itself and provide a custom  location method.
3 posts, 1 answered