In Sitefinity CMS we have a built in ability to modify any control ascx template from the backend, but to implement some custom code-behind logic, we will have to add new web control to our Sitefinity project with Visual Studio.
The main ascx template difference between single item and list view item is the wrapping control – DynamicDetailContainer for single item and RadListView for list view.
Here is how to reach single item template:
Go to Visual Studio and create a Web User Control. Visual Studio will automatically create a template with code behind file. Copy the template code in Visual Studio ascx file, but leave the first line as it contains reference for code behind file:
<%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.DynamicModules.Web.UI.Frontend" TagPrefix="sf" %>
<%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI.Fields" TagPrefix="sf" %>
<%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI" TagPrefix="sf" %>
<
sf:DynamicDetailContainer
id
=
"detailContainer"
runat
=
"server"
>
<
LayoutTemplate
>
<
div
class
=
"sfitemDetails"
>
<
sf:SitefinityLabel
ID
=
"mainShortTextFieldLiteral"
runat
=
"server"
Text='<%# Eval("Title") %>' WrapperTagName="h1" HideIfNoText="true" CssClass="sfitemTitle" />
<
sf:FieldListView
ID
=
"PublicationDate"
runat
=
"server"
Format
=
"{PublicationDate.ToLocal():MMM d, yyyy, HH:mm tt}"
WrapperTagName
=
"div"
WrapperTagCssClass
=
"sfitemPublicationDate"
/>
</
div
>
<
div
>
<%--somecontrol here...--%>
</
div
>
</
LayoutTemplate
>
</
sf:DynamicDetailContainer
>
<
asp:PlaceHolder
ID
=
"socialOptionsContainer"
runat
=
"server"
></
asp:PlaceHolder
>
Now in the code behind we need to subscribe to the ItemDataBound event of the DynamicDetailContainer which is the control that wraps all fields that are rendered:
protected
void
Page_Load(
object
sender, EventArgs e)
{
//attach to the databound event of the container that wraps the whole control
var repeater = (DynamicDetailContainer)
this
.FindControl(
"detailContainer"
);
repeater.DataBound +=
new
EventHandler(repeater_DataBound);
}
void
repeater_DataBound(
object
sender, EventArgs e)
{
//find certain control from the controls collection of the template
var getControl =
this
.FindControl(
"detailContainer"
).Controls[0].FindControl(
"somecontrol"
);
}
As mentioned above for a single item, go to Visual Studio and create a Web User Control:
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI.PublicControls.BrowseAndEdit" Assembly="Telerik.Sitefinity" %>
<%@ 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.Fields" Assembly="Telerik.Sitefinity" %>
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI" Assembly="Telerik.Sitefinity" %>
<%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
<
telerik:RadListView
ID
=
"dynamicContentListView"
ItemPlaceholderID
=
"ItemsContainer"
runat
=
"server"
EnableEmbeddedSkins
=
"false"
EnableEmbeddedBaseStylesheet
=
"false"
>
<
LayoutTemplate
>
<
ul
class
=
"sfitemsList sfitemsListTitleDateTmb"
>
<
asp:PlaceHolder
ID
=
"ItemsContainer"
runat
=
"server"
/>
</
ul
>
</
LayoutTemplate
>
<
ItemTemplate
>
<
li
class
=
"sfitem sfClearfix"
>
<
h2
class
=
"sfitemTitle"
>
<
sf:DetailsViewHyperLink
ID
=
"DetailsViewHyperLink"
TextDataField
=
"Title"
runat
=
"server"
/>
</
h2
>
<
sf:FieldListView
ID
=
"PublicationDate"
runat
=
"server"
Format
=
"{PublicationDate.ToLocal():MMM d, yyyy, HH:mm tt}"
WrapperTagName
=
"div"
WrapperTagCssClass
=
"sfitemPublicationDate"
/>
<%--Add some control (in this case a Repeater)--%>
<
asp:Repeater
ID
=
"RepeaterControl"
runat
=
"server"
>
<
ItemTemplate
> </
ItemTemplate
>
</
asp:Repeater
>
</
li
>
</
ItemTemplate
>
</
telerik:RadListView
>
<
sf:Pager
id
=
"pager"
runat
=
"server"
></
sf:Pager
>
<
asp:PlaceHolder
ID
=
"socialOptionsContainer"
runat
=
"server"
></
asp:PlaceHolder
>
Now in the code behind we need to subscribe to the ItemDataBound event of the RadListView which is the control that wraps all fields that are rendered:
protected
void
Page_Load(
object
sender, EventArgs e)
{
var repeater = (RadListView)
this
.FindControl(
"dynamicContentListView"
);
repeater.ItemDataBound += repeater_ItemDataBound;
}
void
repeater_ItemDataBound(
object
sender, RadListViewItemEventArgs e)
{
if
(e.Item.ItemType == RadListViewItemType.DataItem || e.Item.ItemType == RadListViewItemType.AlternatingItem)
{
//geting the controls on the template from event args as below
var dataItem = e.Item
as
RadListViewDataItem;
if
(dataItem.DataItem !=
null
)
{
var item = dataItem.DataItem
as
DynamicContent;
if
(item !=
null
)
{
var detailLink = e.Item.FindControl(
"DetailsViewHyperLink"
)
as
DetailsViewHyperLink;
var repeat = e.Item.FindControl(
"RepeaterControl"
)
as
Repeater;
}
}
}
}
Add additional fields to template which will be populated with data. To populate the fields use the API for each of the modules you have created (there is API reference for each module in Administration >> ModuleBuilder >> select a module and then click on code reference). Query the modules to retrieve the data to be shown.
Last, the template needs to be registered in Sitefinity - go to ControlDefinition->Views and select the GroupDetails view, and in the textbox TemplatePath enter a path of the template (DetailView for single item and MasterView for list item):
Here you can download single item sample.
Here you can download list view sample.