Extending NewsView

Posted by Community Admin on 05-Aug-2018 22:36

Extending NewsView

All Replies

Posted by Community Admin on 05-May-2011 00:00

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?

Posted by Community Admin on 06-May-2011 00:00

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.

Posted by Community Admin on 06-May-2011 00:00

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 >>

Posted by Community Admin on 06-May-2011 00:00

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

Posted by Community Admin on 11-May-2011 00:00

Antoine, would you mind sharing your module code?

Posted by Community Admin on 03-Jun-2011 00:00

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;
            
        
    

Posted by Community Admin on 03-Jun-2011 00:00

Thanks.

Posted by Community Admin on 31-Oct-2011 00:00

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.

Posted by Community Admin on 28-Nov-2011 00:00

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?

Posted by Community Admin on 13-Jun-2013 00:00

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?

Posted by Community Admin on 17-Jun-2013 00:00

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.

This thread is closed