|
|||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionThis week I stumbled across a problem. I had to display the details of an order. Usually, I just grab a I had to generate output like this:
I'm not trying to have any discussion of the usefulness or the content of this example. The basic thing is that this cannot be easily done with a generic Intended SolutionI wanted to be able to dynamically decide which template to use for each element in my collection. This required me to be able to describe multiple templates in my .asp code: <cc:MyRepeater id="order" runat="server">
<ItemTemplate forClass="OrderRow">
<tr>
<td><%# DataBinder.Eval(Container.DataItem, "Name")%></td>
<td><%# DataBinder.Eval(Container.DataItem, "Price", "C")%></td>
<td><asp:Button id="Remove" CommandName="remove" runat="server"/></td>
</tr>
</ItemTemplate>
<ItemTemplate forClass="OrderDescription">
<tr>
<td colspan="3"><%# DataBinder.Eval(Container.DataItem, "Name")%></td>
</tr>
</ItemTemplate>
</cc:MyRepeater>
During my research, I came upon some pretty nasty stuff that didn't seem possible. After some tedious searching however, I found the solution. SolutionI had to resort to a small change in the model described above. It was not only not possible to add properties to different <cc:ObjectRepeater id="order" runat="server">
<ObjectTemplate name="orderRow">
<ItemTemplate>
<tr>
<td><%# DataBinder.Eval(Container.DataItem, "Name")%></td>
<td><%# DataBinder.Eval(Container.DataItem, "Price", "C")%></td>
<td><asp:Button id="Remove" CommandName="remove" runat="server"/></td>
</tr>
</ItemTemplate>
</ObjectTemplate>
<ObjectTemplate name="description">
<ItemTemplate>
<tr>
<td colspan="3"><%# DataBinder.Eval(Container.DataItem, "Name")%></td>
</tr>
</ItemTemplate>
</ObjectTemplate>
</cc:ObjectRepeater>
I also added a delegate to my private void Page_Load(object sender, System.EventArgs e)
{
order.DetermineTemplate =
new ObjectRepeaterDetermineTemplateDelegate(this.determineTemplate);
}
public string determineTemplate(object sender, object dataItem)
{
if(dataItem is OrderRow)
return "orderRow";
else
return "description";
}
This delegate can also be used to check certain properties of your Implementation DetailsTo be able to implement this solution, I had to develop a templated databound custom control as is described in MSDN quite well. The problem can be divided into three parts:
Problem #1To be able to dynamically add objects, I've overridden Please look at the attached project for details, because this is not really rocket science. The trick lies into adding an Problem #2In the code for private RepeaterItem CreateItem(int itemIndex,
ListItemType itemType, bool dataBind, object dataItem)
{
RepeaterItem item = new RepeaterItem(itemIndex, itemType);
RepeaterItemEventArgs e = new RepeaterItemEventArgs(item);
//decide which template to use.
string templateName = null;
if(dataBind)
{
if(DetermineTemplate != null)
{
templateName = this.DetermineTemplate(this, dataItem);
ViewState["templateName" + itemIndex.ToString()] = templateName;
}
}
else
{
//determine template to use from viewState;
templateName = (string)ViewState["templateName" + itemIndex.ToString()];
}
if(templateName == null)
templateName = this.DefaultTemplate;
CustomDynamicTemplate dynamicTemplate =
(CustomDynamicTemplate)_templates[templateName];
//Must exist.
dynamicTemplate.ItemTemplate.InstantiateIn(item);
if (dataBind)
{
item.DataItem = dataItem;
}
OnItemCreated(e);
this.Controls.Add(item);
if (dataBind)
{
item.DataBind();
OnItemDataBound(e);
item.DataItem = null;
}
return item;
}
For each row, I call a delegate (your delegate) to determine the name of the template. I then look it up in my Problem #3The final problem lies in that the used template (per row) must be maintained in ViewState, otherwise postback event will not fire, or worst, will fire for the incorrect row. In the above code, I maintain Final NotesI've looked around the internet for more on this specific subject, and found little or none about adding dynamic templates. Most people seemed to be stuck on a simpler problem, namely dynamically selecting templates for a whole In conclusion, I hope you liked this article, and maybe you have some use for this class as good as I did! If so, please vote.. (if you didn't, please vote as well).
|
||||||||||||||||||||||||||||||||||