Related Content Items
Hi,
We would like to use tags to show related news and events at news detail view page. I used this thread to display related news items - www.sitefinity.com/.../get-related-news-items-from-tags and it is working fine for news items, but how can I display the events with the same tag?
Thanks,
Igor
Hi Igor,
You could easily replace the calls to the NewsManager with the ones for the EventsManager.
I'll put my code in here, for a reference. It's really just a matter of calling the API for Events.
RelatedEvents.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="RelatedEvents.ascx.cs" Inherits="SitefinityWebApp.Widgets.Events.RelatedEvents" %>
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI.ContentUI" Assembly="Telerik.Sitefinity" %>
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI.Comments" Assembly="Telerik.Sitefinity" %>
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI" Assembly="Telerik.Sitefinity" %>
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI.PublicControls.BrowseAndEdit" Assembly="Telerik.Sitefinity" %>
<%@ Register TagPrefix="sfContent" Namespace="Telerik.Sitefinity.Modules.Events.Web.UI.Export" Assembly="Telerik.Sitefinity.ContentModules" %>
<%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
<%@ Register TagPrefix="events" Namespace="Telerik.Sitefinity.Modules.Events.Web.UI.Public" Assembly="Telerik.Sitefinity.ContentModules" %>
<
telerik:RadListView
ID
=
"eventsList"
ItemPlaceholderID
=
"ItemsContainer"
runat
=
"server"
EnableEmbeddedSkins
=
"false"
EnableEmbeddedBaseStylesheet
=
"false"
>
<
LayoutTemplate
>
<
ul
class
=
"sfeventsList sfeventsListTitleCityDate"
>
<
asp:PlaceHolder
ID
=
"ItemsContainer"
runat
=
"server"
/>
</
ul
>
</
LayoutTemplate
>
<
ItemTemplate
>
<
li
class
=
"sfeventListItem"
>
<
h2
class
=
"sfeventTitle"
>
<
asp:HyperLink
ID
=
"lnkTitle"
runat
=
"server"
></
asp:HyperLink
>
</
h2
>
<
div
class
=
"sfeventMetaInfo"
>
<
sf:FieldListView
ID
=
"PublicationDate"
runat
=
"server"
Format
=
"PublicationDate.ToLocal():MMM dd, yyyy"
/>
</
div
>
</
li
>
</
ItemTemplate
>
</
telerik:RadListView
>
<
sf:Pager
ID
=
"pager"
runat
=
"server"
></
sf:Pager
>
<
asp:PlaceHolder
ID
=
"socialOptionsContainer"
runat
=
"server"
/>
using
System;
using
System.Linq;
using
System.Web.UI;
using
Telerik.OpenAccess;
using
Telerik.Sitefinity.Events.Model;
using
Telerik.Sitefinity.Model;
using
Telerik.Sitefinity.Modules.Events;
namespace
SitefinityWebApp.Widgets.Events
public
partial
class
RelatedEvents : System.Web.UI.UserControl
protected
void
Page_Load(
object
sender, EventArgs e)
var manager = EventsManager.GetManager();
// Get the detail item URL
var itemUrl =
this
.GetUrlParameterString(
true
);
string
redirectUrl =
""
;
// Get the actual event from the URL parameters in details page URL
var eventsItem = manager.GetItemFromUrl(
typeof
(Event), itemUrl,
out
redirectUrl)
as
Event;
if
(eventsItem !=
null
)
var assignedTags = eventsItem.GetValue<TrackedList<Guid>>(
"Tag"
);
var relatedSource = manager.GetEvents().Where(n => n.GetValue<TrackedList<Guid>>(
"Tag"
).Any(t => assignedTags.Contains(t)) && n.Id != eventsItem.Id && n.Status == Telerik.Sitefinity.GenericContent.Model.ContentLifecycleStatus.Live);
//Then we bind the listview
eventsList.DataSource = relatedSource;
eventsList.DataBind();
Hi Daniel,
Thanks for the answer. But the issue is a bit different and I will try to describe it in details:
Let's say we have news 1 with the tag 'test', news 2 with the same tag 'test' and we also have an event with the tag 'test'. When I open news 1 I can see the related items at the right side bar - the related items should include news 2 and the event with the tag 'test'. It's all clear how to display related news, but how can I display the event with the same tag as the news item has?
Any help would be much appreciated.
Thanks,
Igor
Hi Igor,
I see. That is a bit different approach. In short it will mean that you need to know the current newsitem. This can be done through the UrlParameters. After that you can use the API to get the related items.
See the following code for reference:
using
System;
using
System.Collections.Generic;
using
System.Globalization;
using
System.Linq;
using
System.Text;
using
System.Text.RegularExpressions;
using
System.Threading;
using
System.Web;
using
System.Web.UI;
using
System.Web.UI.WebControls;
using
Telerik.OpenAccess;
using
Telerik.Sitefinity.Abstractions;
using
Telerik.Sitefinity.Events.Model;
using
Telerik.Sitefinity.Localization.UrlLocalizationStrategies;
using
Telerik.Sitefinity.Model;
using
Telerik.Sitefinity.Modules;
using
Telerik.Sitefinity.Modules.Events;
using
Telerik.Sitefinity.Modules.News;
using
Telerik.Sitefinity.Modules.Pages;
using
Telerik.Sitefinity.Modules.Pages.PropertyPersisters;
using
Telerik.Sitefinity.News.Model;
using
Telerik.Sitefinity.Pages.Model;
using
Telerik.Sitefinity.Web;
using
Telerik.Web.UI;
using
SitefinityWebApp.CommonCode;
namespace
SitefinityWebApp.Widgets.News.Related
public
partial
class
RelatedEvents : System.Web.UI.UserControl
#region Properties
/// <summary>
/// Gets the manager.
/// </summary>
/// <value>The manager.</value>
protected
EventsManager Manager
get
if
(
this
._manager ==
null
)
this
._manager = EventsManager.GetManager();
return
this
._manager;
protected
PageManager PageManager
get
if
(
this
._pageManager ==
null
)
this
._pageManager = PageManager.GetManager();
return
this
._pageManager;
protected
NewsItem CurrentNewsItem
get
if
(
this
._currentNewsItem ==
null
)
this
._currentNewsItem = Helper.GetCurrentNewsItem(
this
, NewsManager.GetManager(), widgetNameRegularExpression);
return
this
._currentNewsItem;
protected
string
CurrentPageUrl
get
if
(
string
.IsNullOrEmpty(
this
._currentPageUrl))
UrlLocalizationService s = ObjectFactory.Resolve<UrlLocalizationService>();
this
._currentPageUrl = s.ResolvePageUrl(
this
.CurrentPage, Thread.CurrentThread.CurrentUICulture);
return
this
._currentPageUrl;
protected
PageNode CurrentPage
get
if
(
this
._currentPage ==
null
)
SiteMapNode currentNode = SiteMapBase.GetCurrentProvider().CurrentNode;
Guid currentPageId =
new
Guid(currentNode.Key);
this
._currentPage =
this
.PageManager.GetPageNode(currentPageId);
return
this
._currentPage;
public
Guid EventDetailPageId
get
return
_eventDetailPageId;
set
_eventDetailPageId = value;
#endregion
#region Page Events
protected
void
Page_Load(
object
sender, EventArgs e)
this
.RelatedEventsList.ItemDataBound +=
new
EventHandler<Telerik.Web.UI.RadListViewItemEventArgs>(RelatedEventsList_ItemDataBound);
BindData();
#endregion
#region Methods
private
void
BindData()
if
(
this
.GetIndexRenderMode() == Telerik.Sitefinity.Web.UI.IndexRenderModes.Normal)
var items = GetEventItems();
if
(items.Count > 0)
this
.RelatedEventsList.DataSource = items;
this
.RelatedEventsList.DataBind();
/// <summary>
/// Get news items
/// </summary>
/// <returns></returns>
private
List<Event> GetEventItems()
string
categories = RelatedItemsHelper.GetNewsCategories(
this
.CurrentNewsItem);
if
(categories.Count() > 0)
var query =
this
.Manager.GetEvents();
int
? totalCount = 0;
int
? itemsToSkip = 0;
CultureInfo uiCulture =
null
;
if
(AppSettings.CurrentSettings.Multilingual)
uiCulture = System.Globalization.CultureInfo.CurrentUICulture;
string
filter =
"Visible = true AND Status = Live"
;
if
(categories !=
string
.Empty)
filter +=
" AND "
+ categories;
//the filter is adapted to the implementation of ILifecycleDataItemGeneric, so the culture is taken in advance when filtering published items.
filter = ContentHelper.AdaptMultilingualFilterExpression(filter);
var filterExpression = DefinitionsHelper.GetFilterExpression(filter,
null
);
query = Telerik.Sitefinity.Data.DataProviderBase.SetExpressions(
query,
filterExpression,
"PublicationDate DESC"
,
uiCulture,
itemsToSkip,
10,
ref
totalCount);
return
query.ToList();
else
return
new
List<Event>(0);
#endregion
#region Events
/// <summary>
/// Fires on ItemDataBound
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void
RelatedEventsList_ItemDataBound(
object
sender, Telerik.Web.UI.RadListViewItemEventArgs e)
// Get the event item
var item = ((RadListViewDataItem)e.Item).DataItem
as
Event;
// Generate the url for the Event detail page
var eventDetailurl = Helper.GetPageUrl(
this
.EventDetailPageId) + item.ItemDefaultUrl.Value;
// Set the title and link
var lnkEventItem = e.Item.FindControl(
"lnkEventItem"
)
as
HyperLink;
lnkEventItem.Text = item.Title;
lnkEventItem.NavigateUrl = eventDetailurl;
var lnkMore = e.Item.FindControl(
"lnkMore"
)
as
HyperLink;
lnkMore.NavigateUrl = eventDetailurl;
lnkMore.Text =
"Read more"
;
// Set the date
var litDate = e.Item.FindControl(
"litDate"
)
as
Literal;
litDate.Text = item.PublicationDate.ToLongDateString();
#endregion
#region Private variables
private
EventsManager _manager;
private
PageManager _pageManager;
private
PageNode _currentPage;
private
NewsItem _currentNewsItem;
private
string
_currentPageUrl;
private
int
_maxNumberOfItems = 0;
private
const
string
widgetNameRegularExpression = @
"/!(?<urlPrefix>\w+)/.*"
;
private
Guid _eventDetailPageId;
#endregion
Daniel,
Thanks a lot! That worked for me.
Regards,
Igor
Hi Igor,
Great! So the previous post answered your question? *hint*
Kind regards,
Daniel
Sure! Thanks again :-)
Hey Daniel, is there a way to make the types ambigious? I'd like to make a widget that allows you to select the type of content of the detail page (in this post's case it would be news) and the type of content you want to pull associated tags from (in this post's case it would be events).
Hi Mark,
If you want to make it dynamic so that you can choose the type, you will need e.g. a designer. There you could define the types of content you'd like to relate to your current content type, based on the UrlParameter for example.
So yes, that would be a way to make it more flexible.
Is that what you mean?
Kind regards,
Daniel
Yes, I was definitely planning on using a designer, and this is probably more of a question for Telerik, but is there anyway to make some of the replicated code more dynamic.
So in my designer if I choose from a list of content types (Events, News, Blogs) I can choose Events and instead of using
var manager = EventsManager.GetManager();
use
var manager = TypeManager.GetManager();
Probably wishful thinking, but would definitely be helpful.