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

Forums / Sitefinity SDK / Extending NewsView

Extending NewsView

12 posts, 0 answered
  1. Antoine
    Antoine avatar
    45 posts
    Registered:
    13 Jul 2012
    05 May 2011
    Link to this post
    In Sitefinity, if you drop a News widget and a Categories widget on a page, you can use the Category widget to dynamically update the category filter of the News widget.  However, only one category can be selected at once.

    I would like to create a new widget much like the existing News widget, the difference being that the category filter can be dynamically updated with multiple categories selected.  I would also create a new Categories widget that would allow multiple selection of Categories.

    Here is how I imagine doing it:
    - Create a custom control that extends Telerik.Sitefinity.Modules.News.Web.UI.NewsView.
    - In the new control, override the behavior that configures the data source for the telerik:RadListView in the associated control template.

    Is this possible?  How exactly do I go about doing it?
  2. Antoine
    Antoine avatar
    45 posts
    Registered:
    13 Jul 2012
    06 May 2011
    Link to this post
    I think I have made some progress.  I created a user control that extends Telerik.Sitefinity.Web.UI.ContentUI.ContentView, set it with the News control definitions and News module.  After placing the control on a page, it renders news items like the normal News widget.  The control renders a news item listing nicely.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
     
    using Telerik.Sitefinity.Web.UI;
    using Telerik.Sitefinity.Web.UI.ContentUI;
    using Telerik.Sitefinity.Localization;
    using Telerik.Sitefinity.Modules.News;
     
    namespace NewsViewExtended
    {
        public class NewsViewExtended : ContentView
        {
            /// <summary>
            /// Gets or sets the name of the module which initialization should be ensured prior to rendering this control.
            /// </summary>
            /// <value>The name of the module.</value>
            public override string ModuleName
            {
                get
                {
     
                    if (String.IsNullOrEmpty(base.ControlDefinitionName))
                        return NewsModule.ModuleName;
                    return base.ModuleName;
                }
                set
                {
                    base.ModuleName = value;
                }
            }
     
            /// <summary>
            /// Gets or sets the name of the configuration definition for the whole control. From this definition
            /// control can find out all other configurations needed in order to construct views.
            /// </summary>
            /// <value>The name of the control definition.</value>
            public override string ControlDefinitionName
            {
                get
                {
                    if (!String.IsNullOrEmpty(base.ControlDefinitionName))
                        return base.ControlDefinitionName;
                    return "NewsFrontend";
                }
                set
                {
                    base.ControlDefinitionName = value;
                }
            }
     
            /// <summary>
            /// Hides the prices on the front-end from the designer
            ///
            /// </summary>
            /// <value>The name of the hide prices property.</value>
            public bool HidePrices
            {
                get;
                set;
            }
     
            /// <summary>
            /// Gets or sets the name of the master view to be loaded when
            /// control is in the ContentViewDisplayMode.Master
            /// </summary>
            /// <value></value>
            public override string MasterViewName
            {
                get
                {
                    if (!String.IsNullOrEmpty(base.MasterViewName))
                        return base.MasterViewName;
                    return "NewsFrontendList";
                }
                set
                {
                    base.MasterViewName = value;
                }
            }
     
            /// <summary>
            /// Gets or sets the name of the detail view to be loaded when
            /// control is in the ContentViewDisplayMode.Detail
            /// </summary>
            /// <value></value>
            public override string DetailViewName
            {
                get
                {
                    if (!String.IsNullOrEmpty(base.DetailViewName))
                        return base.DetailViewName;
                    return "NewsFrontendDetails";
                }
                set
                {
                    base.DetailViewName = value;
                }
            }
     
            /// <summary>
            /// Gets or sets the text to be shown when the box in the designer is empty
            /// </summary>
            /// <value></value>
            public override string EmptyLinkText
            {
                get
                {
                    return Res.Get<NewsResources>().EditNewsSettings;
                }
            }
        }
    }

    Still have some work to do to get the details view working when I click on a News item.  I will try to work on this soon.

    Unable to cast object of type 'NewsViewExtended.NewsViewExtended' to type 'Telerik.Sitefinity.Modules.News.Web.UI.NewsView'.

    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.InvalidCastException: Unable to cast object of type 'NewsViewExtended.NewsViewExtended' to type 'Telerik.Sitefinity.Modules.News.Web.UI.NewsView'.

    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:

    [InvalidCastException: Unable to cast object of type 'NewsViewExtended.NewsViewExtended' to type 'Telerik.Sitefinity.Modules.News.Web.UI.NewsView'.]
       Telerik.Sitefinity.Modules.News.Web.UI.DetailsSimpleView.InitializeControls(GenericContainer container, IContentViewDefinition definition) +58
       Telerik.Sitefinity.Web.UI.ContentUI.Views.Backend.ViewBase.CreateChildControls() +62
       System.Web.UI.Control.EnsureChildControls() +102
       System.Web.UI.Control.PreRenderRecursiveInternal() +42
       System.Web.UI.Control.PreRenderRecursiveInternal() +175
       System.Web.UI.Control.PreRenderRecursiveInternal() +175
       System.Web.UI.Control.PreRenderRecursiveInternal() +175
    
       ...

    Still haven't determined how I will customize the DataSource for the RadListView.  Any insight is appreciated.
  3. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    09 Dec 2016
    06 May 2011
    Link to this post
    Hi Antoine,

    Do you have your own MasterView and DetailsView? I see that you are calling the base classes for News.


    #region View Definitions

                controlDefinition.ViewsConfig.AddLazy(FrontendListViewName, () =>
                    new ContentViewMasterElement(controlDefinition.ViewsConfig)
                    {
                        ViewName = FrontendListViewName,
                        ViewType = typeof(Telerik.Sitefinity.Samples.Module.Web.UI.Public.MasterView),
                        AllowPaging = true,
                        DisplayMode = FieldDisplayMode.Read,
                        ItemsPerPage = 20,
                        ResourceClassId = typeof(ModuleResources).Name,
                        FilterExpression = DefinitionsHelper.PublishedOrScheduledFilterExpression,
                        SortExpression = "PublicationDate DESC"
                    });


                controlDefinition.ViewsConfig.AddLazy(FrontendDetailViewName, () =>
                    new ContentViewDetailElement(controlDefinition.ViewsConfig)
                    {
                        ViewName = FrontendDetailViewName,
                        ViewType = typeof(Telerik.Sitefinity.Samples.Module.Web.UI.Public.DetailsView),
                        ShowSections = false,
                        DisplayMode = FieldDisplayMode.Read,
                        ResourceClassId = typeof(ModuleResources).Name
                    });

                #endregion

    Regards,
    Ivan Dimitrov
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get now >>

  4. Antoine
    Antoine avatar
    45 posts
    Registered:
    13 Jul 2012
    06 May 2011
    Link to this post
    Ivan, you definitely directed me on the right path by helping me to understand that what I needed to do extend was the Telerik.Sitefinity.Modules.News.Web.UI.MasterListView.

    Here's what I did:

    (1) Extended the News module MasterListView.  I overrode the InitializeControls, copying the code from MasterListView.InitializeControls in the sample Products module.  I customized the method according to my needs.  

    (2) Registered my new MasterListView by creating a new ContentViewMasterElement in Advanced settings entry in ContentView -> Controls -> NewsFrontend -> Views

    (3) Extended the News module NewsView.  I overrode the MasterViewName property to map it to my new MasterListView class.

    (4) Registered my new NewsView in Advanced Settings in Toolboxes -> Toolboxes -> PageControls -> Sections -> ContentToolboxSection -> Tools

    It all worked.  My custom News widget displayed everything like the out-of-box news widget.  I added some custom filtering in the InitializeControls method of my MasterListView and the results were filtered as I expected.

    Later on, I hope to subscribe the view to some kind of filters updated event.  The event handler will update the list using the filter options published with the event.  I think this will involve having the event handler doing everything that InitializeControls does.

    Thanks for your assistance Ivan.

    Antoine
  5. Sonu Kapoor
    Sonu Kapoor avatar
    41 posts
    Registered:
    24 Apr 2006
    11 May 2011
    Link to this post
    Antoine, would you mind sharing your module code?
  6. Antoine
    Antoine avatar
    45 posts
    Registered:
    13 Jul 2012
    03 Jun 2011
    Link to this post
    I'd be happy to share the code.

    NewsViewExtended/MasterListView.cs
    using System;
    using System.Globalization;
    using System.Linq;
    using System.Web.UI;
    using Telerik.Sitefinity;
    using Telerik.Sitefinity.Abstractions;
    using Telerik.Sitefinity.GenericContent.Model;
    using Telerik.Sitefinity.Model;
    using Telerik.Sitefinity.Modules;
    using Telerik.Sitefinity.Web.UI;
    using Telerik.Sitefinity.Web.UI.Comments;
    using Telerik.Sitefinity.Web.UI.ContentUI.Contracts;
    using Telerik.Sitefinity.Web.UI.ContentUI.Views.Backend;
    using Telerik.Sitefinity.Web.UrlEvaluation;
    using Telerik.Web.UI;
    using Telerik.Sitefinity.Web.UI.ContentUI.Views;
    using Telerik.Sitefinity.News.Model;
     
    namespace NewsViewExtended
    {
     
        /**
         * Antoine says:
         * - I copied much of this code from MasterListView.cs in the Products sample project.
         * - I am assuming that the InitializeControls method of the products view is very similar
         *   to the News module MasterListView method that we are overriding.
         * - I added the view in the advanced settings:
         *      ContentView ->
         *      Controls ->
         *      NewsFrontend ->
         *      Views ->
         *      [Create new - ContentViewMasterElement]
         *   For the element, I named it 'NewsExtendedFrontendList' and I copied most of the
         *   values form the NewsFrontendList element.
         */
     
        /// <summary>
        /// Represents master view that displays a collection content items as list.
        ///
        /// This class overrides the out-of-box Master List View so that we can do
        /// our own special filtering of the list items.
        /// </summary>
        public class MasterListView : Telerik.Sitefinity.Modules.News.Web.UI.MasterListView
        {
            /// <summary>
            /// Initializes the controls.
            /// </summary>
            /// <param name="container">The controls container.</param>
            /// <param name="definition">The content view definition.</param>
            protected override void InitializeControls(GenericContainer container, IContentViewDefinition definition)
            {
                var masterDefinition = definition as IContentViewMasterDefinition;
                if (masterDefinition != null)
                {
                    IQueryable<NewsItem> query = this.Manager.GetNewsItems();
                    if (masterDefinition.AllowUrlQueries.HasValue && masterDefinition.AllowUrlQueries.Value)
                    {
                        query = this.EvaluateUrl(query, "Date", "PublicationDate", this.Host.UrlEvaluationMode, this.Host.UrlKeyPrefix);
                        query = this.EvaluateUrl(query, "Author", "Owner", this.Host.UrlEvaluationMode, this.Host.UrlKeyPrefix);
                        query = this.EvaluateUrl(query, "Taxonomy", "", typeof(NewsItem), this.Host.UrlEvaluationMode, this.Host.UrlKeyPrefix);
                    }
     
                    /*
                     * Antoine says:  If we were to perform additional filtering when the page reposts, we could do it here.
                     * If we were to perform filtering when an event is published, we would create an event handler, subscribe
                     * instance to the event, and do all the work there.
                     */
     
                    int? totalCount = 0;
                    int? itemsToSkip = 0;
                    if (masterDefinition.AllowPaging.HasValue && masterDefinition.AllowPaging.Value)
                    {
                        itemsToSkip = this.GetItemsToSkipCount(masterDefinition.ItemsPerPage, this.Host.UrlEvaluationMode, this.Host.UrlKeyPrefix);
                    }
     
                    CultureInfo uiCulture = null;
                    if (AppSettings.CurrentSettings.Multilingual)
                    {
                        uiCulture = System.Globalization.CultureInfo.CurrentUICulture;
                    }
                    var filterExpression = DefinitionsHelper.GetFilterExpression(this.FilterExpression, this.AdditionalFilter);
                    query = Telerik.Sitefinity.Data.DataProviderBase.SetExpressions(
                        query,
                        filterExpression,
                        masterDefinition.SortExpression,
                        uiCulture,
                        itemsToSkip,
                        masterDefinition.ItemsPerPage,
                        ref totalCount);
     
                    this.IsEmptyView = (totalCount == 0);
     
                    if (totalCount == 0)
                    {
                        this.NewsList.Visible = false;
                    }
                    else
                    {
     
                        //this.ConfigurePager(totalCount.Value, masterDefinition);
                        this.NewsList.DataSource = query.ToList();
                        this.NewsList.PreRender += new EventHandler(NewsList_PreRender);
                    }
                }
            }
     
            /// <summary>
            /// Handles the PreRender event of the NewsList control.
            /// </summary>
            /// <param name="sender">The source of the news.</param>
            /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
            private void NewsList_PreRender(object sender, System.EventArgs e)
            {
                //// In ItemDataBound NavigateUrl property of the link is still not set. That is the reason why this logic is implemented in PreRender.
                foreach (var item in this.NewsList.Items)
                {
                    if (item.ItemType == RadListViewItemType.DataItem || item.ItemType == RadListViewItemType.AlternatingItem)
                    {
                        var itemCommentsLink = item.FindControl("itemCommentsLink") as CommentsBox;
                        if (itemCommentsLink != null)
                        {
                            /**
                             * Antoine says:  I commented out this code segement set the comments to not visible.  For this
                             * project, we will never by showing comments.  If we wanted this to be more resuable, we would
                             * allow the user to decide if the commends will be displayed or not.
                             */
                            itemCommentsLink.Visible = false;
                            //var dataItem = item.DataItem as Telerik.Sitefinity.GenericContent.Model.Content;
                            //if (dataItem != null)
                            //{
                            //    var query = this.GetCommentsQuery(dataItem);
                            //    var commentsCount = query.Count();
                            //    itemCommentsLink.CommentsCount = commentsCount;
                            //}
                        }
                    }
                }
            }
     
        }
    }

    NewsViewExtended/NewsViewExtended.cs
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
     
    using Telerik.Sitefinity.Web.UI;
    using Telerik.Sitefinity.Web.UI.ContentUI;
    using Telerik.Sitefinity.Localization;
    using Telerik.Sitefinity.Modules.News;
    using Telerik.Sitefinity.Modules.News.Web.UI;
     
    namespace NewsViewExtended
    {
        /**
         * Antoine says:
         * - I think the only difference between NewsViewExtended and NewsView is that NewsViewExtended
         *   maps to a different MasterView.
         * - I added the widget in the advanced settings:
         *     Toolboxes ->
         *     Toolboxes ->
         *     PageControls ->
         *     Sections ->
         *     ContentToolboxSection ->
         *     Tools ->
         *     [Create new]
         *       ControlType:  NewsViewExtended.NewsViewExtended, NewsViewExtended, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
         *       Name:  NewsViewExtended
         */
     
        /// <summary>
        /// </summary>
        public class NewsViewExtended : NewsView
        {
            /// <summary>
            /// Gets or sets the name of the module which initialization should be ensured prior to rendering this control.
            /// </summary>
            /// <value>The name of the module.</value>
            public override string ModuleName
            {
                get
                {
     
                    if (String.IsNullOrEmpty(base.ControlDefinitionName))
                        return NewsModule.ModuleName;
                    return base.ModuleName;
                }
                set
                {
                    base.ModuleName = value;
                }
            }
     
            /// <summary>
            /// Gets or sets the name of the configuration definition for the whole control. From this definition
            /// control can find out all other configurations needed in order to construct views.
            /// </summary>
            /// <value>The name of the control definition.</value>
            public override string ControlDefinitionName
            {
                get
                {
                    if (!String.IsNullOrEmpty(base.ControlDefinitionName))
                        return base.ControlDefinitionName;
                    return "NewsFrontend";
                }
                set
                {
                    base.ControlDefinitionName = value;
                }
            }
     
            /// <summary>
            /// Hides the prices on the front-end from the designer
            ///
            /// </summary>
            /// <value>The name of the hide prices property.</value>
            public bool HidePrices
            {
                get;
                set;
            }
     
            /// <summary>
            /// Gets or sets the name of the master view to be loaded when
            /// control is in the ContentViewDisplayMode.Master
            /// </summary>
            /// <value></value>
            public override string MasterViewName
            {
                get
                {
                    //if (!String.IsNullOrEmpty(base.MasterViewName))
                    //    return base.MasterViewName;
                    return "NewsExtendedFrontendList";
                }
                set
                {
                    base.MasterViewName = value;
                }
            }
     
            /// <summary>
            /// Gets or sets the name of the detail view to be loaded when
            /// control is in the ContentViewDisplayMode.Detail
            /// </summary>
            /// <value></value>
            public override string DetailViewName
            {
                get
                {
                    if (!String.IsNullOrEmpty(base.DetailViewName))
                        return base.DetailViewName;
                    return "NewsFrontendDetails";
                }
                set
                {
                    base.DetailViewName = value;
                }
            }
     
            /// <summary>
            /// Gets or sets the text to be shown when the box in the designer is empty
            /// </summary>
            /// <value></value>
            public override string EmptyLinkText
            {
                get
                {
                    return Res.Get<NewsResources>().EditNewsSettings;
                }
            }
        }
    }
  7. Sonu Kapoor
    Sonu Kapoor avatar
    41 posts
    Registered:
    24 Apr 2006
    03 Jun 2011
    Link to this post
    Thanks.
  8. Steve
    Steve avatar
    1 posts
    Registered:
    03 Mar 2009
    31 Oct 2011
    Link to this post
    I tried to use the .cs files provided above in sitefinity 4.2 but can not find the correct using statements.  I believe the using Telerik.Sitefinity.Abstractions; are more like Telerik.Abstractions ?  Any ideas on how to get the correct using statements?  I guess I'll use the object browser to individually locate each assembly.

  9. Steve
    Steve avatar
    1 posts
    Registered:
    02 Sep 2011
  10. anthony
    anthony avatar
    3 posts
    Registered:
    18 Oct 2010
    28 Nov 2011
    Link to this post
    I also have a news view extension related query,
    Both a Master and Detail view are placed on the same page

    issue #1

    I need to extend the list view so that it can be sorted dynamically by year. ie 2010, 2011, 2012.
    Would the above method work for this approach?
    ie custom NewsFrontendList? Can you possibly give me a few pointers on how to go about this?

    issue #2
    The details view needs to display the most recent news item,
    (or if selected) most recent new item for selected year,
    specific news item selected
    Can this be done by providing a custom NewsFrontendDetails? How is the single news item being selected?
    It seems to need /Year/month/day/title to access the proper article.

    issue #3
    Is there an RSS feed readily available for the news control?

    I would appreciate any suggestions with respect to how to solve #1 and #2. Am i going to have to write a custom module to get this to work?
  11. Joel
    Joel avatar
    11 posts
    Registered:
    15 Feb 2013
    13 Jun 2013
    Link to this post
    Were you able to open single items in a pre-existing page, instead of an auto generated page? 

    Every time i attempt to set "Selected existing page..." when configuring the widget my MasterViewName is always reset to the default (but the item opens in a pre-existing page), but when i attempt to re-enter the custom masterview name, the open single items option reverts back to an auto-generated page.

    Any ideas?
  12. Patrick Dunn
    Patrick Dunn avatar
    237 posts
    Registered:
    03 Nov 2014
    17 Jun 2013
    Link to this post
    Hi Joel,

     This issue is 2 years old and for a much older version of Sitefinity. Can you submit a support ticket describing what you're trying to accomplish, what you've done so far, and a video to demonstrate the problems you're experiencing with your implementation?

    Regards,
    Patrick Dunn
    Telerik

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

12 posts, 0 answered