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

Forums / Developing with Sitefinity / Getting access to content list repeater

Getting access to content list repeater

19 posts, 0 answered
  1. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    23 Sep 2010
    Link to this post
    Hello,

    I have a public control that lists out multiple items from a generic content module. The template has a repeater.

    Within my code I have set:

    protected override void OnLoad(EventArgs e) {
     
        ((Repeater)oRepeater).ItemDataBound += new RepeaterItemEventHandler(CaseStudyPublicView_ItemDataBound);

    However, this never triggers the event handler, I suspect because Siteinfity has already bound the repeater's
    datasource before the onload handler is triggerered.

    How do i get access to the repeaters itemdatabound handler? What method do i have to override?

    Thanks
    higgsy
  2. Radoslav Georgiev
    Radoslav Georgiev avatar
    3370 posts
    Registered:
    01 Feb 2016
    23 Sep 2010
    Link to this post
    Hello Alastair,

    Databind method of the repeater control is called in CreateChildControls method. You can subscribe to the repeater data bind event execution in the CreateContentList method of your custom content view:
    protected override void CreateContentList()
    {
        base.CreateContentList();
        ListContainer.RepeaterControl.ItemDataBound += new System.Web.UI.WebControls.RepeaterItemEventHandler(RepeaterControl_ItemDataBound);
    }
     
    void RepeaterControl_ItemDataBound(object sender, System.Web.UI.WebControls.RepeaterItemEventArgs e)
    {
        //throw new NotImplementedException();
    }

    The other option is to do this from the control template itself (not the content view class). You can add this script snippet:
    <script type="text/C#" runat="server">
        protected void Page_Load()
        {
            repeater.ItemDataBound += new RepeaterItemEventHandler(repeater_ItemDataBound);
        }
      
        void repeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
            {
     
            }
        }
    </script>


    Sincerely yours,
    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
  3. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    23 Sep 2010
    Link to this post
    Hi Radoslav,

    Thanks for your response, however that didnt work for me - the itemdatabound handler was not triggered. It was however when i changed it to:

    protected override System.Collections.IList CreateDataSource() {
     
        oRepeater.ItemDataBound += new RepeaterItemEventHandler(CaseStudyPublicView_ItemDataBound);
        return base.CreateDataSource();
    }

    And to access the repeater oRepeater:

    //find the repeater
            protected virtual Repeater oRepeater {
                get {
                    return base.ListContainer.RepeaterControl;
                }
            }

    Hope this helps.

    Al
  4. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    23 Sep 2010
    Link to this post
    Hi Radoslav,

    Quick follow-on question.

    Each of the content items within the repeater datasource has a field called category. In the repeater header i need to list out each of the unique categories in the datasource.

    Any thoughts on how i could acheive this?

    Regards,
    higgsy
  5. Radoslav Georgiev
    Radoslav Georgiev avatar
    3370 posts
    Registered:
    01 Feb 2016
    23 Sep 2010
    Link to this post
    Hi Alastair,

    You can create an array, IList or List<> of  categories or whatever is your object. Then check if the array contains the current item bound's category, if not add the category to the item.

    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
  6. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    23 Sep 2010
    Link to this post
    That was what i thought would probably be the answer....so i tried the following:

    System.Collections.IList oList = oRepeater.DataSource;
    System.Web.UI.WebControls.DataGrid oGrid = new DataGrid();
    oGrid.DataSource = oList;
    oGrid.DataBind();
    this.Page.Controls.Add(oGrid);

    I'm just using the grid to see what fields are within the datasource.

    However, that returns the error:

    A field or property with the name 'LoweredUrl' was not found on the selected data source.


    Any ideas as to why?

    Regards,
    higgsy
  7. Radoslav Georgiev
    Radoslav Georgiev avatar
    3370 posts
    Registered:
    01 Feb 2016
    23 Sep 2010
    Link to this post
    Hi Alastair,

    Ahm, the above code is not what I suggested. From what I can see from the code you are adding the whole data source of the repeater to a grid. I do not see any checks for unique items at all. IList and List<> and array objects have a method Contains() which returns true or false depending on whether their collection of items contains the item you are checking for.

    1) Create a new field of type List<YourType> or whatever is your item as part of your control class.

    2) In the method where you subscribe tho the ItemDataBound event of the repeater before this instantiate the list of categories. Also subsribe to DataBound event execution of the repeater.
    yourList = new List<YourType>();

    3) In ItemDataBound event check if yourList.Contains(((YourClass)e.Item.DataItem).Category) or whaterver field it is. If false add the category to the list using yourList.Add()

    4) In DataBound event of the repeater use the populated list and add it to the header of the repeater or somewhere.

    Greetings,
    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
  8. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    23 Sep 2010
    Link to this post
    Sorry Radoslav,

    Im a bit lost. Should it be something like the following:
    private List<CaseStudies> oList;
     
    public class CaseStudies {
     
        public IContent oContent { get; set; }
     
    }

    And then before i register the itemdatabound:

    protected override System.Collections.IList CreateDataSource() {
     
        oList = new List<CaseStudies>();
     
        //register repeater events
        oRepeater.ItemDataBound += new RepeaterItemEventHandler(CaseStudyPublicView_ItemDataBound);
        oRepeater.PreRender += new EventHandler(oRepeater_PreRender);
     
        //store a value of the number of records in the datasource
        _iRecordCount = base.Manager.ContentCount();
     
        //bind the datasource
        return base.CreateDataSource();
    }

    Then something like:

    void CaseStudyPublicView_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
     
        if (oList.Contains(((CaseStudies)e.Item.DataItem))) {
     
     //not sure what to do here???
             
        }

    Thanks
    higgsy
  9. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    23 Sep 2010
    Link to this post
    Hello Alastair,

    I am not sure what exactly you are trying to do, but if you subscribe for ItemDataBound event of the repeater inside CreateContentList the event should be fired. Then cast e.Item.DataItem to IContent item to get reference to the IContent object.

    Regards,
    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
  10. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    24 Sep 2010
    Link to this post
    Hi Radoslav,

    Ok, im getting there. I just have two remaining questions.

    My repeater looks like so:

    <HeaderTemplate>
       
    <div>
    </HeaderTemplate>
    <ItemTemplate>
    <asp:PlaceHolder runat="server" id="plhContent"/>
    </ItemTemplate>
    <FooterTemplate>
       
    </div>
    </FooterTemplate>

    I then have a dataset that looks like:

    Title | Category
    "Title1","Legal"
    "Title2","Legal"
    "Title3","Finance"
    "Title4","Accounting"

    The dataset is sorted by the category.

    And the output im trying to achieve is:

    <div><!-- from headertemplate -->
       
    <div id="legal">
           
    <ul>
               
    <li>Title 1</li>
               
    <li>Title 2</li>
           
    </ul>
       
    </div><!--end legal div-->
       
    <div id="Finance">
           
    <ul>
               
    <li>Title 3</li>
           
    </ul>
       
    </div><!--end finance div-->
       
    <div id="Accounting">
           
    <ul>
               
    <li>Title 4</li>
           
    </ul>
       
    </div><!--end accounting div-->
    </div><!-- from footertemplate -->

    However I'm really struggling with the logic. Within my code i've essentially got:

    Add a bulleted list
    Add a listitem

    But this poses a problem for the row "title2" because it doesnt require a new bulleted list, it just requires a new listitem to be added to the bulleted list in the previous iteration of the repeater.

    How can i possibly do this?

    Lastly, you mention binding to the repeaters DataBound event handler, but the repeater doesnt have a databound handler, do you mean disposed or unload?

    Thanks in advance

    higgsy

  11. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    24 Sep 2010
    Link to this post
    Hi Alastair,

    You need a custom control that inherits from ContentView. You have to use nested repeaters - the first one will shows the categories and the second one will show the items per category.

    The layout of the template should be something like

    <asp:Repeater runat="server" ID="categoryRepeater">
        <ItemTemplate>
         <asp:Literal runat="server" ID="contentCategory"></asp:Literal>
          <asp:Repeater runat="server" ID="itemsRepeater">
              <ItemTemplate>
               <asp:HyprLink runat="server" ID="contentTitle"></asp:HyperLink>
              </ItemTemplate>
            </asp:Repeater>
        </ItemTemplate>
    </asp:Repeater>

    After you bind the first repeater you have to bind the second one inside ItemDataBound of the first
    repeater. This will allow you to group the items by category and you will not crate a new <ul> for items with common category.

    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
  12. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    27 Sep 2010
    Link to this post
    Hi IVan,

    Yes that makes sense. Couple of quick questions:

    I have a custom control that inherits from ContentView. It has a ListView and SingleItemView.

    The the moment the datasource is getting each contentitem and the repeater is looping through them. I will presumably need to change the datasource so that it is just getting the categories. How would i do this? There is a Sitefinity method CreateDataSourceByCategory but its listed as depreciated.

    Thanks
    higgsy
  13. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    27 Sep 2010
    Link to this post
    Hi,

    Could i just clarify how to achieve the following.

    I have a control that inherits from ContentView. There is a List and SingleItem view.

    I am trying to group the contentitems by their Category. For example each contentitem has a category, and on the page im going to be displaying content items in a tab system, each tab representing a unique category.

    I think i need to achieve this like so, but am unclear:

    1) Use a nested repeater. The top level repeater will become the datasource for the categories. This presumably means i need to override the default datasource.

    2) Use a nested repeater for the content items - how will i create a custom data source filtered by a meta data field i.e. Category?

    Thanks again
    higgsy


    Therefore, presumably i want to just override the datasource for the listed view.
  14. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    27 Sep 2010
    Link to this post
    Hello Alastair,

    If you inherit from ContentView and want to have such grouping you will lose some of the features that comes with ContentView class, because you have to change the datasource and structure of the main repeater, but ContentView relies  on both parameters here - datasource and repeater structure.

    You have to create a custom control that inherits from SimpleView and nest the repeaters.

    sample

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Telerik.Cms.Web.UI;
    using System.Web.UI.WebControls;
    using System.Collections;
    using Telerik.Cms.Engine;
      
     
    public class SimpleViewControl  : SimpleControl
    {
     
      
        public override string LayoutTemplatePath
        {
            get
            {
                return "~/CustomControls/SimpleViewTemplate.ascx";
            }
            set
            {
                base.LayoutTemplatePath = value;
            }
        }
      
        protected override void InitializeControls(System.Web.UI.Control controlContainer)
        {
            base.InitializeControls(controlContainer);
      
            if (MainRepeater != null)
            {
                MainRepeater.DataSource = GetCategoryDataSource();
                MainRepeater.ItemDataBound += new RepeaterItemEventHandler(MainRepeater_ItemDataBound);
                MainRepeater.DataBind();
            }
        }
      
        void MainRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
            {
                var c = e.Item.DataItem as ICategory;
      
                Literal categoryLiteral = e.Item.FindControl("contentCategory") as Literal;
                if (categoryLiteral != null)
                {
                    categoryLiteral.Text = c.CategoryName;
                }
                Repeater nesterRepeater = e.Item.FindControl("itemsRepeater") as Repeater;
                if (nesterRepeater != null)
                {
                    nesterRepeater.DataSource = GetContentDataSource(categoryLiteral.Text);
                    nesterRepeater.ItemDataBound += new RepeaterItemEventHandler(nesterRepeater_ItemDataBound);
                    nesterRepeater.DataBind();
                }
            }
        }
      
        void nesterRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
            {
               var cntItem =  e.Item.DataItem as IContent;
      
               HyperLink link =  e.Item.FindControl("contentTitle") as HyperLink;
               if (link != null)
               {
                   link.Text = (string)cntItem.GetMetaData("Name");
                   link.NavigateUrl = cntItem.UrlWithExtension;
               }
            }
        }
      
        protected virtual Repeater MainRepeater
        {
            get
            {
                return this.Container.GetControl<Repeater>("categoryRepeater", true);
            }
        }
      
        private IList GetContentDataSource(string CategoryName)
        {
            var cntManager = new ContentManager("Generic_Content");
            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", CategoryName));
            return cntManager.GetContent(0, 0, filter.ToArray());
        }
      
        private IList<ICategory> GetCategoryDataSource()
        {
            var cntManager = new ContentManager("Generic_Content");
            IList allCategories =  cntManager.GetCategories();
            List<ICategory> filteredList = new List<ICategory>();
            foreach (ICategory category in allCategories)
            {
                int number = GetCategoryCount(category);
                if (number != 0)
                {
                    filteredList.Add(category);
                }
            }
            return filteredList;
        }
      
      
        int GetCategoryCount(ICategory category)
        {
            var Manager = new ContentManager("Generic_Content");
            IList categoriesTree = Manager.GetCategoriesTree(category);
            List<IMetaSearchInfo> filter = new List<IMetaSearchInfo>();
            foreach (ICategory categoryItem in categoriesTree)
                filter.Add(new MetaSearchInfo(MetaValueTypes.ShortText, "Category", categoryItem.CategoryName, SearchCondition.Equal, JoinType.And));
      
            int contentCount = Manager.GetContent(filter.ToArray()).Count;
            return contentCount;
        }
      
    }


    <asp:Repeater runat="server" ID="categoryRepeater">
        <ItemTemplate>
         <asp:Literal runat="server" ID="contentCategory"></asp:Literal>
          <asp:Repeater runat="server" ID="itemsRepeater">
              <ItemTemplate>
               <asp:HyperLink runat="server" ID="contentTitle"></asp:HyperLink>
              </ItemTemplate>
            </asp:Repeater>
        </ItemTemplate>
    </asp:Repeater>

    You can extend and style the control.

    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
  15. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    27 Sep 2010
    Link to this post
    Hi Ivan,

    Thanks for your response. Will the ContentView not support nested repeaters?

    The reason i ask is because i tried it and the nested repeater never displays???

    higgsy
  16. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    27 Sep 2010
    Link to this post
    Hi Alastair,

    Out of the box ContentView does not support nested repeaters and you need to implement this logic in a similar way that my code shows. I hope that this make sense.

    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
  17. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    27 Sep 2010
    Link to this post
    Ok - what do i lose with SimpleControl over ContentView then? Will it still display single and list views???
  18. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    27 Sep 2010
    Link to this post
    Hello Alastair,

    SimpleControl class provides properties for using  a template. It inherits from CompositeControl class. In this case you will not have filtering, sorting, details mode etc.

    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
  19. higgsy
    higgsy avatar
    336 posts
    Registered:
    05 Aug 2010
    27 Sep 2010
    Link to this post
    Ok,

    Thats not so bad, it just means i will have to create two controls - one for single and one for list.

    Finally, can i just replace:

    var Manager = new ContentManager("Generic_Content");

    With

    var Manager = new ContentManager("CaseStudy");

    so that it uses the same provider as my module??

    Thanks
    higgsgy
Register for webinar
19 posts, 0 answered