More in this section

Forums / Developing with Sitefinity / Custom Images & Documents Module

Custom Images & Documents Module

15 posts, 1 answered
  1. Bobby
    Bobby avatar
    56 posts
    Registered:
    11 Feb 2009
    19 Jun 2010
    Link to this post
    Hi,

        I have a client that has a hierachial structure called reserach areas. They allow a document to be tagged with multiple research areas.  I can't just use the tags functionality out of the box because it does not have a hierarchial structure. So, I believe I need to create a custom module that inherits from the document and images module with the following changes to achieve my goal. 

    I would like to allow the user the use the default behavior of the categories control to create the hierarchy of categories(ie. research areas). I would make the tags control invisible for the custom module. Instead of using the default combo box control to display the research areas, I would use a tree control. When the user selects the research areas on the add or edit of a document and saves the content, I would then read the selected research areas and save those categories as tags for the document. When a user edits a document, I would find the tags associated with that document and check the matching categories that applied in my tree control of categories.

    My first question is,
    Is this the right approach to my problem?
    My second question is, if this is a good approach, what is the easiest way to override the Images and Documents functionality? In my intial attempt, my custom module was showing the same libraries as the default Images and Documents module. I wanted the modules to be independent. I know I am doing something wrong. Can you point me in the right directon.

    Thanks in advance,
    Bobby
  2. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    21 Jun 2010
    Link to this post
    Hello Bobby,

    If you inherits from Images and Documents module you are getting all base logic - views, controls, hierarchy.
    You have to override some of the methods in the base view and its controls. By default the categories are added to a RadComboBox and this is a custom control - ContentCategoriesField. The RadComboBox is required control and the easiest way is just to hide it and add RadTreeView which is bound to all categories. You could get all categories for your provider by using GetCategories() method of the LibraryManager. The method returns IList of ICategory objects.
    The ContentCategoriesField is declared under LibraryItemEdit.ascx external template. The control ContentCategoriesField has  a public property - LayoutTemplatePath which you can use to map CategoriesField.ascx template where RadComboBox declaration resides. So, from CategoriesField.ascx you could hide the default control.

    To make the association between categories and tags you need to replace the default view - LibraryItemEdit with a custom one and override SaveContent() method where you could check the selected categories and set tags for the IContent item



    Best wishes,
    Ivan Dimitrov
    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. Bobby
    Bobby avatar
    56 posts
    Registered:
    11 Feb 2009
    22 Jun 2010
    Link to this post
    Hi Ivan,


    Thank you for your response. This is what I believe I have been missing, how to replace views and templates and plug them into the Sitefinity architecture. I will try this when I get home this evening. I have another question in regards to this one. Can you explain how a my custom module that's based on the images and documents module will have different documents libraries than the orginal one. In my custom module, the same libraries that are defined in the original Images and Documents library appear in my custom module. Again thanks for you help. I really appreciate it.

  4. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    22 Jun 2010
    Link to this post
    Hi Bobby,

    Since you are making "inheritance" you will get all the base logic. You can change it only by overriding some of the views and the methods. Generally the inheritance is used when you want to "upgrade" a class or tweak it, so you do not start from scratch. In such cases the main problem is when some of the methods cannot be accessed.

    Sincerely yours,
    Ivan Dimitrov
    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
  5. Bobby
    Bobby avatar
    56 posts
    Registered:
    11 Feb 2009
    22 Jun 2010
    Link to this post
    Thanks Ivan,

        I understand what you mean and just tweaking the Images and documents module is what I want to do. However, I am still trying to understand how the provider model works when accessing data from a custom module when inheritance is not used. For example, I used your ProductsModule example as a guide to create another custom generic module with success. The data was saved into Sitefinity's structure but I am unclear on how this happened. Can you point me in the write direction to get information on how the provider model works with custom modules and how it comes into play in the web.config file?
     
    Thanks,
    Bobby
  6. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    22 Jun 2010
    Link to this post
    Hello Bobby,

    You could take a look at

    GenericContent based modules use data provider - Telerik.Cms.Engine.Data.Providers.DefaultProvider. The provider implements methods where the Nolics transactions are executed and the data is retrieved/saved.

    Greetings,
    Ivan Dimitrov
    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
  7. Bobby
    Bobby avatar
    56 posts
    Registered:
    11 Feb 2009
    22 Jun 2010
    Link to this post

    Hi again,

    I have followed the direction that you gave me but I have done something wrong. Below is the code from my custom controls config xml and my custom class. Can you see what I am doing wrong? The default view is not being replaced by my custom view.


    Below is the contents from App_Data/Configuration/Telerik.Sitefinity.Configuration.ControlsConfig..xml


    <?xml version="1.0" encoding="utf-8"?>
    <controlsConfig>
        <viewMap>
            <!--Provides user interface for displaying a list of bloggers in the blogs module. -->
            <viewSettings hostType="Telerik.Libraries.WebControls.Admin.LibraryItemsView, Telerik.Libraries">
                <views>
                    <remove name="LibraryItemEdit"></remove>
                    <add name="LibraryItemEdit" viewType="ResearchAreas.WebControls.Admin.ResearchAreaLibraryItemEdit, ResearchAreas"></add>
                </views>
            </viewSettings>
        </viewMap>
    </controlsConfig>

    The following is the code from my custom class




    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Telerik.Cms.Engine.WebControls.Admin;
    using System.Web.UI;
    using Telerik.Framework.Web;
    using Telerik.Web.UI;
    using Telerik.Libraries;
    using Telerik.Cms.Engine;
    using Telerik.Libraries.WebControls.Admin;

    namespace ResearchAreas.WebControls.Admin
    {
        public class ResearchAreaLibraryItemEdit : Telerik.Libraries.WebControls.Admin.LibraryItemEdit
        {
            private string layoutTemplate = "ResearchAreas.Resources.ControlTemplates.Backend.ResearchAreaLibraryEdit.ascx";

            protected override void InitializeControls(Control viewContainer)
            {
                LibraryManager manager = new LibraryManager();

                RadTreeView researchAreas = ResearchAreas;
                researchAreas.DataSource = manager.GetCategories();
                researchAreas.DataFieldID = "ID";
                researchAreas.DataFieldParentID = "ParentCategoryID";
                researchAreas.DataTextField = "CategoryName";
                researchAreas.DataValueField = "ID";
                researchAreas.DataBind();
            }

            public override System.Type LocalizationAssemblyInfo
            {
                get
                {
                    return typeof(LibraryItemEdit);
                }
                set
                {
                    base.LocalizationAssemblyInfo = value;
                }
            }

            public override System.Type AssemblyInfo
            {
                get
                {
                    return typeof(LibraryItemEdit);
                }
                set
                {
                    base.AssemblyInfo = value;
                }
            }  


            protected override Telerik.Cms.Engine.WebControls.Admin.IContentCategoriesField CategoriesControl
            {
                get
                {
                    return (IContentCategoriesField)base.Container.GetControl<Control>("Category", false, TraverseMethod.BreadthFirst);
                }
            }

            public override string LayoutTemplatePath
            {
                get
                {
                    return layoutTemplate;
                }
                set
                {
                    layoutTemplate = value;
                }
            }

            protected RadTreeView ResearchAreas
            {
                get
                {
                    return base.Container.GetControl<RadTreeView>("treeResearchAreas", true, TraverseMethod.BreadthFirst);
                }
            }

            protected override void SaveContent()
            {

                base.SaveContent();
            }
        }
    }
  8. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    23 Jun 2010
    Link to this post
    Hello Bobby,

    The mapping looks fine.

    Try the following

    1. Restart the application, because the changes to ControlsConfig applies after application restart.
    2. Make sure that the template you use has been build as EmbeddedResource
    3. You could set the template as public const string

    Let me know how it goes.

    Greetings,
    Ivan Dimitrov
    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
  9. Bobby
    Bobby avatar
    56 posts
    Registered:
    11 Feb 2009
    23 Jun 2010
    Link to this post
    Hi Ivan,

        My resource is set to embedded. I have restarted IIS and I have tried your suggestion of making my template variable a public const as you have suggested also. However, it's not pointing to my custom template. If I introduce an error in the ControlsConfig file, will sitefinity throw an exception? I have tried to do this by pointing to an invalid library name but no exception was thrown. Is there a way to know if Sitefinity is attempting to apply my custom view. Below is my custom view code. I have replaced my LayoutTemplatePath with LayoutTemplateName. Is there anything that jumps out?

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Telerik.Cms.Engine.WebControls.Admin;
    using System.Web.UI;
    using Telerik.Framework.Web;
    using Telerik.Web.UI;
    using Telerik.Libraries;
    using Telerik.Cms.Engine;
    using Telerik.Libraries.WebControls.Admin;

    namespace ResearchAreas.WebControls.Admin
    {
        public class ResearchAreaLibraryItemEdit : Telerik.Libraries.WebControls.Admin.LibraryItemEdit
        {
            public const string layoutTemplate = "ResearchAreas.Resources.ControlTemplates.Backend.ResearchAreaLibraryItemEdit.ascx";

            protected override void InitializeControls(Control viewContainer)
            {
                LibraryManager manager = new LibraryManager();
                manager = null;

                RadTreeView researchAreas = ResearchAreas;
                researchAreas.DataSource = manager.GetCategories();
                researchAreas.DataFieldID = "ID";
                researchAreas.DataFieldParentID = "ParentCategoryID";
                researchAreas.DataTextField = "CategoryName";
                researchAreas.DataValueField = "ID";
                researchAreas.DataBind();
            }

            public override System.Type LocalizationAssemblyInfo
            {
                get
                {
                    return typeof(LibraryItemEdit);
                }
                set
                {
                    base.LocalizationAssemblyInfo = value;
                }
            }

            public override System.Type AssemblyInfo
            {
                get
                {
                    return typeof(LibraryItemEdit);
                }
                set
                {
                    base.AssemblyInfo = value;
                }
            }

            /// <summary>
            /// Gets the name of the embedded layout template. This property must be overridden to provide the path (key) to an embedded resource file.
            /// </summary>
            /// <value></value>
            protected override string LayoutTemplateName
            {
                get
                {
                    return layoutTemplate;
                }
            }
         
            protected override Telerik.Cms.Engine.WebControls.Admin.IContentCategoriesField CategoriesControl
            {
                get
                {
                    return (IContentCategoriesField)base.Container.GetControl<Control>("Category", false, TraverseMethod.BreadthFirst);
                }
            }

            protected RadTreeView ResearchAreas
            {
                get
                {
                    return base.Container.GetControl<RadTreeView>("treeResearchAreas", true, TraverseMethod.BreadthFirst);
                }
            }

            protected override void SaveContent()
            {

                base.SaveContent();
            }
        }
    }

  10. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    23 Jun 2010
    Link to this post
    Hi Bobby,

    I attached a sample project where the view is replaces and the template is mapped properly. You can observe the project locally. You could use admin/admin to access the project.

    All the best,
    Ivan Dimitrov
    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
  11. Bobby
    Bobby avatar
    56 posts
    Registered:
    11 Feb 2009
    23 Jun 2010
    Link to this post
    Hi Ivan,

        Thanks for your reply. I made a mistake on the name of my Telerik.Sitefinity.Configuration.ControlsConfig.xml file. I didn't notice that my file was name Telerik.Sitefinity.Configuration.ControlsConfig..xml. Sitefinty is now recognizing my custom view. Thanks for all your help.
  12. Bobby
    Bobby avatar
    56 posts
    Registered:
    11 Feb 2009
    23 Jun 2010
    Link to this post
    Hi Ivan,

        I almost have my Custom ListItemEdit control working properly. My RadTreeControl is loading correctly with my research areas. However, my override to SaveContent() is not being called. In my SaveContent() function, all I am doing is a simple redirect to test if it's being called. However, I never get redirectred when I save the content. The following is my code.


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Telerik.Cms.Engine.WebControls.Admin;
    using System.Web.UI;
    using Telerik.Framework.Web;
    using Telerik.Web.UI;
    using Telerik.Libraries;
    using Telerik.Cms.Engine;
    using Telerik.Libraries.WebControls.Admin;
    using System.Collections;
    using System.Web;

    namespace ResearchAreas.WebControls.Admin
    {
        public class ResearchAreaLibraryItemEdit : Telerik.Libraries.WebControls.Admin.LibraryItemEdit
        {
            public const string layoutTemplate = "ResearchAreas.Resources.ControlTemplates.Backend.ResearchAreaLibraryItemEdit.ascx";
            private Guid contentId;

            protected ILibrary CurrentLibrary
            {
                get
                {
                    ILibrary library = null;
                    contentId = this.DataItemId;
                    if (this.contentId != Guid.Empty)
                    {
                        IContent currState = this.Host.LibManager.GetCurrentState(contentId, true);
                        if (currState == null)
                        {
                            currState = this.Host.LibManager.GetStagedContent(contentId);
                        }

                        if (currState != null)
                        {
                            Guid libraryId = currState.ParentID;
                            library = this.Host.LibManager.GetLibrary(libraryId);
                           
                        }
                    }
                    return library;
                }
            }

            protected override void InitializeControls(Control viewContainer)
            {
                base.InitializeControls(viewContainer);

                RadTreeView researchAreas = CurrentResearchArea;
                researchAreas.DataSource = Host.LibManager.GetCategories();
                researchAreas.DataFieldID = "ID";
                researchAreas.DataFieldParentID = "ParentCategoryID";
                researchAreas.DataTextField = "CategoryName";
                researchAreas.DataValueField = "ID";
                researchAreas.CheckBoxes = true;
                researchAreas.CheckChildNodes = true;
                researchAreas.DataBind();

                IList tags = Host.LibManager.GetTags(contentId);
                if (tags.Count > 0)
                {
                    IEnumerable<ITag> strongTags = tags.Cast<ITag>();
                    foreach (ITag tag in strongTags)
                    {
                        RadTreeNode node = researchAreas.FindNodeByText(tag.TagName);
                        if (node != null)
                        {
                            node.Checked = true;
                        }
                    }
                }
            }

            public override System.Type LocalizationAssemblyInfo
            {
                get
                {
                    return typeof(LibraryItemEdit);
                }
                set
                {
                    base.LocalizationAssemblyInfo = value;
                }
            }

            public override System.Type AssemblyInfo
            {
                get
                {
                    return GetType();
                }
                set
                {
                    base.AssemblyInfo = value;
                }
            }

            /// <summary>
            /// Gets the name of the embedded layout template. This property must be overridden to provide the path (key) to an embedded resource file.
            /// </summary>
            /// <value></value>
            protected override string LayoutTemplateName
            {
                get
                {
                    return layoutTemplate;
                }
            }
         
            protected override Telerik.Cms.Engine.WebControls.Admin.IContentCategoriesField CategoriesControl
            {
                get
                {
                    return (IContentCategoriesField)base.Container.GetControl<Control>("Category", false, TraverseMethod.BreadthFirst);
                }
            }

            protected RadTreeView CurrentResearchArea
            {
                get
                {
                    ILibrary currentLib = CurrentLibrary;

                    RadTreeView researchAreas = null;

                    switch (currentLib.TypeName)
                    {
                        case "Image":
                            researchAreas = ImageResearchAreas;
                            break;
                        default:
                            researchAreas = ItemResearchAreas;
                            break;
                    }

                    return researchAreas;
                }
            }

            protected RadTreeView ItemResearchAreas
            {
                get
                {
                    return base.Container.GetControl<RadTreeView>("treeViewItemResearchAreas", true, TraverseMethod.BreadthFirst);
                }
            }

            protected RadTreeView ImageResearchAreas
            {
                get
                {
                    return base.Container.GetControl<RadTreeView>("treeViewImageResearchAreas", true, TraverseMethod.BreadthFirst);
                }
            }

            protected override void SaveContent()
            {
                HttpContext.Current.Response.Redirect("http://www.google.com");
    /*
                RadTreeView researchAreas = CurrentResearchArea;

                List<string> tags = new List<string>();
                tags = null;
                foreach (RadTreeNode checkedNode in researchAreas.CheckedNodes)
                {
                    tags.Add(checkedNode.Text);
                }

                if (tags.Count > 0)
                {
                    Host.LibManager.SaveTags(this.contentId, tags);
                }

                base.SaveContent();
     */
            }
        }
    }

  13. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    23 Jun 2010
    Link to this post
    Hi Bobby,

    You need to subscribe for the Click events of the Save buttons.

    protected override void InitializeControls(System.Web.UI.Control viewContainer)
           {
               base.InitializeControls(viewContainer);
               Label label = new Label();
               label.Text = "HELLO THERE THIS TEMPLATE HAS BEEN MAPPED AND THIS IS THE CODE THAT COMES FROM InitializeControls OF TestLibrary.LibraryItemEditCustom";
               Controls.Add(label);
     
        
               SaveButton1.Click += new EventHandler(SaveButton1_Click);
               SaveButton2.Click += new EventHandler(SaveButton2_Click);
           }
     
           void SaveButton2_Click(object sender, EventArgs e)
           {
               //
           }
     
           void SaveButton1_Click(object sender, EventArgs e)
           {
            //
           }

    It looks like that SaveContent is not called.

    All the best,
    Ivan Dimitrov
    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
  14. Bobby
    Bobby avatar
    56 posts
    Registered:
    11 Feb 2009
    23 Jun 2010
    Link to this post
    Thanks Ivan that works perfectly. Hopefully, this is my last question on this topic. But, when I remove the TagsView via the Telerik.Sitefinity.Configuration.ControlsConfig.xml file, the link to the TagsView doesn's disappear from the Command Panel. However, if I click on the TagsView link, an exception is thrown saying the The ViewMode "TagsView" is not defined for this control. What is the best way to get the TagsView removed from both the Controls Panel and the Command Panel? My config file has 

    <viewSettings hostType="Telerik.Libraries.WebControls.Admin.LibrariesControlPanel, Telerik.Libraries">
       <views>
        <remove name="TagsView"></remove>
       </views>
      </viewSettings>
  15. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    24 Jun 2010
    Link to this post
    Hello Bobby,

    In case that someone is looking into this thread the discussion has been moved here

    All the best,
    Ivan Dimitrov
    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
Register for webinar
15 posts, 1 answered