+1-888-365-2779
Try Now
More in this section

Forums / Developing with Sitefinity / Generic Content Module with sortable categories?

Generic Content Module with sortable categories?

13 posts, 0 answered
  1. mexner
    mexner avatar
    98 posts
    Registered:
    06 Apr 2006
    03 Mar 2010
    Link to this post
    Hello, I have written several custom modules inheriting from the generic content module. I have a couple of questions I am hoping you can give me some direction on...

    1)
    How can I sort the categories? From both the Admin perspective and my public interface control?
    I see that there is a "GetCategories" Method residing inside of Telerik.Cms.Engine.ContentManager
    http://www.sitefinity.com/help/developer-manual/categories-get.html
    And this allows you to specify a sort criteria. The only search criteria I believe will work is using "CategoryName Asc/Desc".

    But what I'm talking about is more of allowing the user to define the order of the categories. So as the user creates "Category 1", they can give it a sorting order. Such as "10". The second category can have a sorting order of "20". Then in the GetCategories method, I can specify a search criteria of "sortOrder", which will sort the "10" and "20".

    That is my thought process, but I don't know how to execute it. I don't see how I can add custom fields to the category content like I can for Generic Content (Name, Category, description, author, etc). If I could, I would add a custom field of "sortOrder" to categories and that would solve my problems.

    Do you have any suggestions on how to allow the user to specify sorting capabilities to categories?

    Just so you know the purpose behind this, my module is an accumulation of data - and the public user starts with a list of categories and drills down into the content. My client needs the ability to sort the categories, and not just alphabetically.

    2)
    Using the same custom modules mentioned above that I have created to inherit from the Generic Content Module, I need to allow my Content to be assigned to more than 1 category. The categories appear to have a 1:1 relationship with the content piece, whereas I need a 1:M type of relationship. I know how I can change the admin area to not use a drop down list, and instead a check box list, but that won't work - because I know the logic inherint to SF isn't saving it in the DB that way.
    Do you have any work-around for this?

    I've thought about using the Tag feature, as it allows you to specify more than 1 "tag/category" per content item. And I think that would work wonderfully, but the problem with that approach, is my business requirement requires the ability to nest categories, and tagging doesn't support that.

    Do you have any suggestions on how I can provide my users the ability to select multiple categories for an individual content item in the admin area?

    Thanks for your help and suggestions,
    Chris

  2. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    09 Dec 2016
    04 Mar 2010
    Link to this post
    Hi mexner,

    1. You can sort by ICategory interface members

    • ID
    • Application
    • CategoryName
    • DateCreated
    • ContentCount
    • ParentCategoryID
    Using the data class you can sort by two more properties

    • ContentProviderName;
    • Owner;

    Both backend and frontend controls (CategoryTree) uses RadTreeView. So basically you need to change the order in the list which is used by RadTreeView control when bound.

    You can take a look at this post that show how to bind the RadTreeView control to categories list - Filter CategoriesTree control by Blog.


    2. You should create a new metakey that will be used with the same purpose as the default Category. The category is a metakey and each content item can be associated with one metakey. Tags are not metakeys and this is why you can assign multiple tags to an IContent.

    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.
  3. mexner
    mexner avatar
    98 posts
    Registered:
    06 Apr 2006
    08 Mar 2010
    Link to this post
    Ivan, thank you for the quick response.

    Is there any "outside the box" ideas you can come up with that will allow me to sort the categories per an additional property? The default sorting options (ID, Application,CategoryName,DateCreated,ContentCount,ParentCategoryID) don't allow the user to define the order of categories manually. I need a way that my client can manually sort the categories the way the need them. Any ideas on this?

    ----
    2. You should create a new metakey that will be used with the same purpose as the default Category. The category is a metakey and each content item can be associated with one metakey. Tags are not metakeys and this is why you can assign multiple tags to an IContent.

    Are you saying that I can add an additional metakey of "Category2" or something similar and have the ability to select 2 categories per IContent? Although not a perfect solution, that is going to solve my problem of having an IContent assigned to multiple categories.

    If I mis-understood you and that is not the case, is their any way I can have an IContent assigned to multiple categories?

    Thanks Ivan,
  4. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    09 Dec 2016
    08 Mar 2010
    Link to this post
    Hello mexner,

    1. You need  a custom module and custom data provider. Your data provider should implement the extended ICateogry interface.

    2. Create an additional metakey that will be used with the same purpose as ICategory. You can use DropDownList control that will be bound to a list of provider categories. You can use ContentManager.GetCategories method.

    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.
  5. mexner
    mexner avatar
    98 posts
    Registered:
    06 Apr 2006
    08 Mar 2010
    Link to this post
    Ivan, gotcha, that makes sense. Do you have any examples of implementing a custom data provider that extends the ICategory interface?

    Thanks again,
  6. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    09 Dec 2016
    08 Mar 2010
    Link to this post
    Hi mexner,

    Crate a custom interface

    namespace Telerik.Samples
    {
        /// <summary>
        /// Extends ICategory by providing new capabilities
        /// </summary>
        public interface ICustomizedCategory : ICategory
        {
      
            string SomeField{ get; set; }
        }
    }

    Create a custom dbclass that uses your custom fields and persist the data to the database.

    namespace Telerik.Cms.Engine.Data;
     
    dbclass Category[TableName = "sf_CmsCategory", ClassName = "CmsCategory"]
    {  
        primary key string Application[50], guid ID[AutoGenGUID = True];
        string SomeField[500];
        bool InheritsPermissions;
        string CategoryName[250];
        date DateCreated;
        guid ParentID;
        guid ParentCategoryID;
         
        string Owner[250];
    }

    Crating a data class

    public partial class Category : ICustomizedCategory , IOdbEventCreate
    {
     
            .....
    }

    You should better create your custom module with a custom data provider. You can take a look at - Working with Data in Sitefinity. I suggest that you should use OpenAccess or Linq- SQL. From Sitefinity 4.0 we will use OpenAccess. Implementing a module with nolics will not be a good solution.

    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.
  7. mexner
    mexner avatar
    98 posts
    Registered:
    06 Apr 2006
    08 Mar 2010
    Link to this post
    Thanks Ivan, I will give that a shot. As for #2,

    2. Create an additional metakey that will be used with the same purpose as ICategory. You can use DropDownList control that will be bound to a list of provider categories. You can use ContentManager.GetCategories method.

    This is my web method used to return IContent pieces when a particular category is selected.  The problem I'm encountering is that my filter is now returning duplicate rows.

    Before when there was only 1 category, I could successfully return all the IContent pieces under that category. However, now that I have added multiple metakeys for additional category assignments, I'm having difficulty returning my IContent pieces for the various categories.

    I have tried all variations of the Telerik.CMS.Engine.JoinType parameter in the Telerik.CMS.Engine.IMetaSearchInfo IList as my filter.

    I've got the admin piece figured out, my question pertains to my custom code below that renders to the site visitor. They select a particular category, and from that selection, I need to return the IContent that has been assigned.

    Web.config

    <add key="QandA.Name" valueType="ShortText"  visible="True" searchable="True" sortable="True" defaultValue="Question..." mandatory="True" localizable="true" />
           <add key="QandA.Category" valueType="ShortText" visible="True" searchable="True" sortable="True"  defaultValue="" localizable="true"/>
           <add key="QandA.Category2" valueType="ShortText" visible="True" searchable="True" sortable="True"  defaultValue="" localizable="true"/>
           <add key="QandA.Category3" valueType="ShortText" visible="True" searchable="True" sortable="True"  defaultValue="" localizable="true"/>
           <add key="QandA.Category4" valueType="ShortText" visible="True" searchable="True" sortable="True"  defaultValue="" localizable="true"/>
           <add key="QandA.Category5" valueType="ShortText" visible="True" searchable="True" sortable="True"  defaultValue="" localizable="true"/>
           <add key="QandA.Description" valueType="LongText" visible="True" searchable="False" sortable="True"  defaultValue="Add description here" localizable="true"/>
           <add key="QandA.Author" valueType="ShortText" visible="True" searchable="True" sortable="True"  defaultValue="" />

    Custom code that is called by my control

    [WebMethod(true)]
        public static string getSermons(string catGUID)
        {
            Telerik.Cms.Engine.ContentManager content = new Telerik.Cms.Engine.ContentManager(_provider);
             
            if (catGUID == null) return "Error, null provided as ID for getSermons";
     
            string resp = createListItem(ListItemPiece.Start, null);
            string temp;
     
            //locate the exact category from the GUID provided
            Telerik.Cms.Engine.ICategory cat = content.GetCategory(new Guid(catGUID));
     
            //create a filter, to only return content in this category
            List<Telerik.Cms.Engine.IMetaSearchInfo> filter = new List<Telerik.Cms.Engine.IMetaSearchInfo>();
            filter.Add(new Telerik.Cms.Engine.MetaSearchInfo(Telerik.Cms.Engine.MetaValueTypes.ShortText, "Category", cat.CategoryName, Telerik.Cms.Engine.JoinType.Or));
            filter.Add(new Telerik.Cms.Engine.MetaSearchInfo(Telerik.Cms.Engine.MetaValueTypes.ShortText, "Category2", cat.CategoryName, Telerik.Cms.Engine.JoinType.And));
            filter.Add(new Telerik.Cms.Engine.MetaSearchInfo(Telerik.Cms.Engine.MetaValueTypes.ShortText, "Category2", cat.CategoryName, Telerik.Cms.Engine.JoinType.Or));
            filter.Add(new Telerik.Cms.Engine.MetaSearchInfo(Telerik.Cms.Engine.MetaValueTypes.ShortText, "Category3", cat.CategoryName, Telerik.Cms.Engine.JoinType.Or));
            filter.Add(new Telerik.Cms.Engine.MetaSearchInfo(Telerik.Cms.Engine.MetaValueTypes.ShortText, "Category4", cat.CategoryName, Telerik.Cms.Engine.JoinType.Or));
            filter.Add(new Telerik.Cms.Engine.MetaSearchInfo(Telerik.Cms.Engine.MetaValueTypes.ShortText, "Category5", cat.CategoryName, Telerik.Cms.Engine.JoinType.Or));
             
     
            //returns all the content items, filtered for this category.
            IList contentList = content.GetContent(filter.ToArray());
     
            if (contentList.Count > 0)
            {
                foreach (Telerik.Cms.Engine.IContent item in contentList)
                    resp += createListItem(ListItemPiece.Item, buildLink("slide", "sermon", item.ID.ToString(), item.GetMetaData("Name").ToString(), null, false));
            }
            else return "Sorry, there aren't any Q&A's for \"" + cat.CategoryName + "\"";
     
            resp += createListItem(ListItemPiece.End, null);
            return resp;
        }
  8. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    09 Dec 2016
    08 Mar 2010
    Link to this post
    Hello mexner,

    You can use JoinType.And and Condition.In. The parameter "Or" that you have used is not supported by Nolics.

    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.
  9. mexner
    mexner avatar
    98 posts
    Registered:
    06 Apr 2006
    08 Mar 2010
    Link to this post
    Ivan, I really appreciate all your help. Thank you very much.
    I don't have "Condition.In" as you referenced.
    I'm using SF 3.7.2022.1
  10. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    09 Dec 2016
    08 Mar 2010
    Link to this post
    Hi mexner,

    You can use ContentfilterBuilder class

    ContentFilterBuilder filterBuilder = new ContentFilterBuilder(this);
    filterBuilder.AddFilter(new ContentFilterStatement("Category", categoryNames,
    ContentFilter.Condition.In,ContentFilter.JoinType.And));


    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. mexner
    mexner avatar
    98 posts
    Registered:
    06 Apr 2006
    11 Mar 2010
    Link to this post
    Ivan, thanks again for the help. I don't believe that is going to work for us, as my method/logic reside in a class, not a page. I'm having a problem with

    new ContentFilterBuilder(this)

    as "this" is undefined.

    Moving forward, is it possible to place a request to have the category functionality include a "sorting" feature? Just curious if I can throw that into the feature request list. Or do you know if it's already planned?

    We are also utilizing the localization features of the Generic Content class in our custom module. I'm not seeing a way to localize the category names or tags. Am I overlooking this feature? Or is it a known bug? I am able to localize everything else in our custom module.

    Thanks Ivan,
  12. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    09 Dec 2016
    11 Mar 2010
    Link to this post
    Hi mexner,

    The current API expose method for sorting categories GetCategories(0, 100, SortExp) - overload of GetCategories, but this is a missing implementation. Actually you can use IComparer Interface to sort the RadTreeNodeCollection after data binding. Categories order is important and it should not be altered.
    Whenever there is persisted order, sorting has to be disabled

    For 4.0 we will have only sorting for tags for the backend.

    There is not implementation for localizable categories and tags. Again you can achieve this but you have to override CategoriesView, ContentItemEdit and ContentItemNew views. The ICategory does not keep the current culture. So, when you create a category in CategoriesView you need to override AddNewCategory() and AddSubcategory() virtual methods. Here you need to have a custom table where you need to store the current culture and category name, then call the base. Then when you bind the RadTreeView or another control that you use for CategoriesView you need to get the current culture and bind the relevant items in InitializeControls method.
    For Edit and New views you need to do the same - populate the Categories DropDown depending on the current culture. Note that you will have the same category names in [sf_GCMetaData] and [sf_CmsCategory] tables.


    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.
  13. Mark
    Mark avatar
    86 posts
    Registered:
    08 Feb 2010
    14 Feb 2011
    Link to this post
    Hi mexner

    I noticed you had a module for sermons
    I'm about to try and do something similar for my church and was wondering if you could give some advice

    Did you store audio files in here and allow for streaming?
    did you also provide sermon notes?

    Thanks
    Mark
Register for webinar
13 posts, 0 answered