Browse DevX
Sign up for e-mail newsletters from DevX


Dynamic Templates for the Repeater, DataList and DataGrid Controls : Page 2

This article explains why a single template hard-coded at design-time is not always the best option when using DataGrid, DataList and Repeater controls that must generate different outputs according to the logged-in user, a user's choice, or any other condition. It then provides detailed solutions to implement dynamic templates, by writing external user controls, or classes that implement the ITemplate interface.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

However, there is still a thing you may argue about: with this method the template is read from file every time the page loads. Even if this I/O operation shouldn’t impact on performances, we can improve the way the template is loaded, by loading it from file just the first time the template is required, and storing it into the cache for future uses. Here’s a function that does what described:

Private Function GetTemplate(ByVal templateFile As String) As ITemplate ' if the file has been already loaded and saved into the cache, ' load it from there If Not Cache(templateFile) Is Nothing Then Trace.Write("Template " & templateFile & " loaded from cache") Return CType(Cache(templateFile), ITemplate) Else ' otherwise load the template file... Dim template As ITemplate = Page.LoadTemplate(templateFile) ' ...and save it into the cache, with a dependency to the original ' file, so that if the file is modified the cache item is removed Cache.Insert(templateFile, template, _ New Caching.CacheDependency(Server.MapPath(templateFile))) Trace.Write("Template " & templateFile & " loaded from file") Return template End If End Function

When inserting the loaded template into the Cache collection we add a dependency to the source template file, so that if it is updated, the cached template is discarded, and the fresh version is loaded at the next page load. The Page.LoadMethod call used above can now be replaced as follows:

Datalist1.ItemTemplate = GetTemplate("DataList_TemplateEx.ascx")

To check whether the template is actually loaded from the cache from the second time the page is loaded, do the following:

1)       Enable the tracing by setting to true the enabled attribute of the trace tag in the Web.Config file.

2)       Refresh the page a couple of times

3)       Point the browser to trace.axd, and you’ll get a list of links to see the tracing details of each page execution. In these details pages you’ll actually see the trace messages that confirm the fact that the template has been cached and reused since the second page execution.

The figure below shows two partial screenshot from the two details pages in question:

So far I’ve shown examples with the DataList only. Working with the Repeater and the DataGrid is very similar though. To dynamically load templates in a DataGrid, you must use TemplateColumn columns, left empty as shown in the following code:

<asp:DataGrid runat="server" ID="Datagrid1" AutoGenerateColumns="False" Width="100%" ItemStyle-BackColor="LightCyan" ItemStyle-ForeColor="DarkBlue" AlternatingItemStyle-BackColor="LightYellow" AlternatingItemStyle-ForeColor="Maroon" ...other style formatting...> <Columns> <asp:BoundColumn DataField="EmployeeID" HeaderText="ID" ItemStyle-Width="20" ItemStyle-BackColor="LightGreen" /> <asp:TemplateColumn HeaderText="Employee Info" /> </Columns> </asp:DataGrid>

All you would need to change in the template file is the cast: in this case you must cast the Container object to the DataGridItem type not to DataListItem because that is the type of the DataGrid's items. The same would be for a Repeater, you would have to cast to a RepeaterItem. In the sample code provided as a separate download for this article, you can find full examples for all these controls. The code below instead is the complete implementation for the Page_Load event, that show how it’s actually the same to load a template for a Repeater and a DataList, and also for a DataGrid, once we have a reference to its template column that we want to use as container for the template:

Private Sub Page_Load() Handles MyBase.Load ' show the welcome message with the current username UserName.Text = User.Identity.Name.Substring( _ User.Identity.Name.IndexOf("\") + 1) ' get a reference to the DataGrid’s template column Dim templCol As TemplateColumn = CType( _ Datagrid1.Columns(1), TemplateColumn) ' load the proper templates according to the logged-in user If User.IsInRole("BUILTIN\Administrators") Then Repeater1.ItemTemplate = GetTemplate("Repeater_TemplateEx.ascx") Datalist1.ItemTemplate = GetTemplate("DataList_TemplateEx.ascx") templCol.ItemTemplate = GetTemplate("DataGrid_TemplateEx.ascx") Else Repeater1.ItemTemplate = GetTemplate("Repeater_TemplateSimple.ascx") Datalist1.ItemTemplate = GetTemplate("DataList_TemplateSimple.ascx") templCol.ItemTemplate = GetTemplate("DataGrid_TemplateSimple.ascx") End If BindControls() End Sub

The BindControls method takes care of retrieving the data to show from the database, and bind it to the template controls. It uses a DataSet instead of a DataReader, because the data must be bound to three controls, so it makes perfect sense to retrieve the data only once and then use it for multiple controls:

Private Sub BindControls() ' fill a DataSet's DataTable with all the data from ' the Northwind's Employees table Dim cn As New SqlConnection( _ ConfigurationSettings.AppSettings("NWConnString")) Dim cmd As New SqlCommand("SELECT * FROM Employees", cn) Dim ds As New DataSet() Dim da As New SqlDataAdapter(cmd) da.Fill(ds, "Employees") ' bind that table to all the template-based controls Repeater1.DataSource = ds.Tables("Employees") Repeater1.DataBind() Datalist1.DataSource = ds.Tables("Employees") Datalist1.DataBind() Datagrid1.DataSource = ds.Tables("Employees") Datagrid1.DataBind() End Sub

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date