I've created a SearchResults
control that shows the results of a search. This control has a repeating element (displaying the results) but also contains other elements which I've removed for this question.
Currently in the following example DataItem
cannot be resolved. I'm trying to work out how to make DataItem
resolvable so I can use this control in the following way:
<Controls:SearchResults runat="server" id="Results">
<RowHeaderTemplate>
<tr>
<td>User ID</td>
</tr>
</RowHeaderTemplate>
<RowItemTemplate>
<tr>
<td>
<%#((Models.User)Container.DataItem).ID %>
</td>
</tr>
</RowItemTemplate>
</Controls:SearchResults>
It is used in this way:
var searchResults = GetSearchResults();
Results.DataSource = searchResults ;
Results.DataBind();
Search Results Control Code:
[System.ComponentModel.DefaultBindingProperty("DataSource")]
public partial class Search : UserControl
{
[PersistenceMode(PersistenceMode.InnerProperty), TemplateContainer(typeof(TemplateControl))]
public ITemplate RowHeaderTemplate { get; set; }
[PersistenceMode(PersistenceMode.InnerProperty), TemplateContainer(typeof(TemplateControl))]
public ITemplate RowItemTemplate { get; set; }
public IEnumerable<object> DataSource { private get; set; }
private bool DataBindingComplete { get; set; }
public override void DataBind()
{
if (DataBindingComplete) return;
foreach (var obj in DataSource)
{
var newControl = new PlaceHolder();
RowItemTemplate.InstantiateIn(newControl);
RowItemContainer.Controls.Add(newControl);
}
DataBindingComplete = true;
base.DataBind();
}
protected void Page_Load(object sender, EventArgs e)
{
if (!Visible) return;
OnInit(e);
if (RowHeaderTemplate != null)
{
RowHeaderTemplate.InstantiateIn(RowHead);
}
}
}
With the markup:
<asp:PlaceHolder runat="server" ID="Wrapper">
<h2>Results</h2>
<table border="1">
<asp:PlaceHolder runat="server" ID="RowHead"/>
<asp:Placeholder runat="server" Visible='<%#TotalResults == 0 %>'>
<tr>
<td colspan="100">
No results returned!
</td>
</tr>
</asp:Placeholder>
<asp:Placeholder runat="server" ID="RowItemContainer" Visible='<%#TotalResults > 0 %>'>
</asp:PlaceHolder>
</table>
</asp:PlaceHolder>
Please note this is a trimmed down example, simply using a Repeater
control in place of it wont suffice.
The problem is that the TemplateContainer attribute for the Search control's RowItemTemplate property references TemplateControl, which doesn't have a DataItem property. Instead of using TemplateControl, create a SearchItem control that has a DataItem property:
In the Search class, change the TemplateContainer attribute for the RowItemTemplate property so that it references SearchItem instead of TemplateControl:
Also, instantiate SearchItem instead of PlaceHolder in DataBind:
These are the minimum changes needed to get your example to work. However, your custom control won't automatically persist items across postbacks. To implement that functionality, I recommend that you study the source code for the Repeater class.