Implementing the features of the control
After you have created the empty user control, you must implement sample functionality in it. The NewsRotator control implements the following main features:
- Loading of the news items and their respective images in the Thumbnails album
- Displaying of summary of the news item, its title, image and a link to the full item
- Scrolling through the available news items and their thumbnails in a slideshow mode
- Loading of a limited number of news items
Before you begin,you must add references to the following assemblies:
-
Telerik.Sitefinity.Model
- Telerik.Sitefinity.ContentModules
- Telerik.OpenAccess
- System.Web.Extensions
- System.Runtime.Serialization
You must also add the following using statements in the NewsRotator.ascx.cs file.
using Telerik.Sitefinity;
using Telerik.Sitefinity.GenericContent.Model;
using Telerik.Web.UI;
using Telerik.Sitefinity.News.Model;
using System.ComponentModel;
using Telerik.Sitefinity.Web.DataResolving;
using Telerik.Sitefinity.Pages.Model;
using Telerik.Sitefinity.Modules.News.Web.UI;
Using the RadRotator control
To display the news items in your control, you must use an ASP.NET control that is capable of handling dynamic data. Examples for such controls are ListBox, GridView, etc. The tutorial uses the RadRotator control. It is part of the RadControls for ASP.NET AJAX, which are shipped together with Sitefinity SDK. The RadRotator can display its items in a slideshow manner.
TIP: For more information about the RadRotator control, see its documentation.
The RadRotator control is located in the Telerik.Web.UI assembly. By default the Sitefinity project should contain a reference to it. To create an instance of the control, declare the appropriate namespace in your user control. Following is the code you must add to theNewsRotator.ascx file:
<%@ Register TagPrefix="sf" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
<sf:RadRotator id="RadRotator1" runat="server" RotatorType="SlideShow">
</sf:RadRotator>
The declaration of the sf namespace, allows you to use any control inside the Telerik.Web.UI namespace in the Telerik.Web.UI assembly. After that you only create an instance of the RadRotator control with RotatorType property set to SlideShow. Write down the ID of the control, because later you will use it to access the control through the codebehind file.
Defining the RadRotator's ItemTemplate
To specify the layout for the items displayed in the RadRotator control, you must specify an ItemTemplate for it. In this tutorial, you must provide UI elements for the news item's image, title, summary, and link to the full item. Here is a sample representation of the required UI:
<sf:RadRotator ID="RadRotator1" runat="server" RotatorType="SlideShow">
<ItemTemplate>
<div>
<div>
<asp:Image runat="server" ID="newsImage" />
</div>
<div>
<asp:Label runat="server" ID="newsTitle" />
<asp:Label runat="server" ID="newsText" />
<asp:HyperLink runat="server" ID="newsLink"><span>Read more...</span></asp:HyperLink>
</div>
</div>
</ItemTemplate>
</sf:RadRotator>
Note that server controls are used with a specific ID, because you will need to access them in the codebehind later.
Limiting the number of the displayed news items
Next you must query the available news items and pass them to the RadRotator's DataSource property. Before doing that, define a property, which limits the count of the news items listed in the control, by opening the NewsRotator.ascx.cs file and inserting the following code:
private int newsLimit = 8;
public virtual int NewsLimit
{
get
{
return this.newsLimit;
}
set
{
this.newsLimit = value;
}
}
By default Sitefinity creates a field for each of your public properties in the control designer of the control. Later you can use the field generated for the NewsLimit property, to specify a value. If you do not want to generate a field for the NewsLimit property, mark it with a[Browsable(false)] attribute.
NOTE: Sitefinity automatically handles persistence in the background. The private backing field serves only as the default value of theNewsLimit property.
TIP: You can categorize the properties, which are added to the control designer of the control. To add a property to a specific category, mark it with the [Category("CategoryName")] attribute.
Querying the news items
After defining a property for the limit of the news items, you must query the news items and pass them to the DataSource property of theRadRotator control. To do this you should use Sitefinity's Fluent API. It allows you to access and use the data from your Sitefinity modules.
NOTE: This example assumes that the images are placed in an album Thumbnails and that their names match the ones of the news items. You must create an image library and name it Thumbnails, upload the thumbnail images and set the title of each image to the title of the news article you want the image to be connected to.
Following is the code, which you must place inside the Page_Load handler in the NewsRotator.ascx.cs file:
protected void Page_Load(object sender, EventArgs e)
{
this.RadRotator1.DataSource = App.WorkWith()
.NewsItems()
.Where(n => n.Status == ContentLifecycleStatus.Live)
.Get()
.Take(this.NewsLimit)
.ToList()
.Join(App.WorkWith()
.Images()
.Get()
.Where(i => i.Parent.Title == "Thumbnails" && i.Status == ContentLifecycleStatus.Live),
item => item.Title.Value,
image => image.Title.Value,
(item, image) => new { NewsItem = item, NewsImage = image });
this.RadRotator1.ItemDataBound += this.RadRotator1_ItemDataBound;
this.RadRotator1.DataBind();
}
private void RadRotator1_ItemDataBound(object sender, RadRotatorEventArgs e)
{
}
The result of the query is a list of anonymous objects each containing a news item and its associated thumbnail.
TIP: For more information about querying news items with the Fluent API, see News. For more information about querying images and other media files, see Media modules.
NOTE: News items that have no corresponding image, are not included in the resulting set.
After setting the DataSource property of the RadRotator control, an event handler is attached to the ItemDataBound event, and theDataBind() method is called. The method causes the RadRotator to bind to the data inside its data source. Event ItemDataBound is raised for each item that is created. Because anonymous types are used, this is the most suitable place for you to define the bindings between the UI elements in the ItemTemplate and the data items passed to it. Following is the code for the handler for the ItemDataBound event:
private void RadRotator1_ItemDataBound(object sender, RadRotatorEventArgs e)
{
var link = e.Item.FindControl("newsLink") as HyperLink;
var image = e.Item.FindControl("newsImage") as Image;
var title = e.Item.FindControl("newsTitle") as Label;
var text = e.Item.FindControl("newsText") as Label;
NewsItem newsItem = (NewsItem)TypeDescriptor.GetProperties(e.Item.DataItem)["NewsItem"].GetValue(e.Item.DataItem);
Telerik.Sitefinity.Libraries.Model.Image newsImage = (Telerik.Sitefinity.Libraries.Model.Image)TypeDescriptor.GetProperties(e.Item.DataItem)["NewsImage"].GetValue(e.Item.DataItem);
if (image != null) image.ImageUrl = newsImage.MediaUrl;
if (title != null) title.Text = newsItem.Title;
if (text != null) text.Text = newsItem.Summary;
if (link != null && TargetNewsPage != null) link.NavigateUrl = DataResolver.Resolve(newsItem, "URL", null, TargetNewsPage.Id.ToString());
}
First, you get the references to the controls inside the ItemTemplate. After that, because the DataItem, which is passed to the RadRotator's item is an anonymous object, you call TypeDescriptor.GetProperties() to access the NewsItem and NewsImage properties. Finally, you set the title, text, image URL, and the link to the full news item. Bacause this link must point to a page that hosts a NewsView control, you should manually make query and get this page. In the following example the TargetNewsPage is represented by a read-only property:
private PageNode targetNewsPage;
protected PageNode TargetNewsPage
{
get
{
if (this.targetNewsPage == null)
{
this.targetNewsPage = App.WorkWith().Pages()
.Where(p => p.Page != null &&
p.Page.Controls.Where(c => c.ObjectType.StartsWith(typeof(NewsView).FullName)).Count() > 0)
.Get().FirstOrDefault();
} //it can still be null in case there is no page with a NewsView on it
return this.targetNewsPage;
}
}
Using the Fluent API, you get the first page which has a NewsView in it. This is the page, which the links for the full news items must point to.
NOTE: If you don't want to use the built-in property editor, you can create a control designer. The control designer allows you to define a custom UI that is used to configure the control.