Extending NewsView
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?
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;
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.
|
|
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
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
Antoine, would you mind sharing your module code?
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;
//
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;
Thanks.
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.
This link was the answer http://www.sitefinity.com/devnet/kb/sitefinity-4-x/an-error-%E2%80%9Ccould-not-load-file-or-assembly-telerik-sitefinity-migrationcontracts-or-one-of-its-dependencies-%E2%80%9D-is-thrown-when-you-rebuild-or-clean-your-sitefinity-4-2-project.aspx
I needed to add back the references.
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?
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?
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,