Below is the html source view of the custom templated databound control. Note that it is currently referencing an ObjectDataSource control. The SelectMethod property of the ObjectDataSource control calls a method named GetStudents which returns List<Student>
<demo:SimpleTemplatedControl
ID="myTemplatedControl"
runat="server"
DataSourceID="ObjectDataSource1">
<ItemTemplate>
<asp:Label
ID="labelTemp"
runat="server"
Text='<%# Eval("FirstName") %>'>
</asp:Label>
<hr />
</ItemTemplate>
</demo:SimpleTemplatedControl>
<asp:ObjectDataSource
ID="ObjectDataSource1"
runat="server"
SelectMethod="GetStudents"
TypeName="DataTestManager">
</asp:ObjectDataSource>
In the example above, the custom control contains an ItemTemplate, and the Eval expression is used to bind to the FirstName property of the Student object returned from the ObjectDataSource.
The first bit of code needed is to create a container control for the ItemTemplate. Here is a minimal implementation:
1 public class SimpleItem : Control, IDataItemContainer
2 {
3 public SimpleItem(object dataItem, int index)
4 {
5 _DataItem = dataItem;
6 _DataItemIndex = _DisplayIndex = index;
7 }
8
9 private object _DataItem;
10 public object DataItem
11 {
12 get { return _DataItem; }
13 }
14
15 private int _DataItemIndex;
16 public int DataItemIndex
17 {
18 get { return 0; }
19 }
20
21 private int _DisplayIndex;
22 public int DisplayIndex
23 {
24 get { return 0; }
25 }
26 }
Lines 9 through 25 are required members of IDataItemContainer. Although this class inherits from Control, it does not contain any behavior for rendering. It will be used in the SimpleTemplatedControl below:
1 public class SimpleTemplatedControl : CompositeDataBoundControl
2 {
3
4 private ITemplate _ItemTemplate;
5 [PersistenceMode(PersistenceMode.InnerProperty),
6 TemplateContainer(typeof(SimpleItem))]
7 public ITemplate ItemTemplate
8 {
9 get { return _ItemTemplate; }// get
10 set { _ItemTemplate = value; }// set
11 }// property
12
13 protected override int CreateChildControls(
14 System.Collections.IEnumerable dataSource,
15 bool dataBinding)
16 {
17 int count = 0;
18 if (dataBinding)
19 {
20 foreach (object dataItem in dataSource)
21 {
22 if (ItemTemplate!=null)
23 {
24 // create instance of SimpleItem control
25 SimpleItem item =
26 new SimpleItem(dataItem, count++);
27
28 // instantiate in new item object
29 ItemTemplate.InstantiateIn(item);
30
31 // add item to Controls collection
32 this.Controls.Add(item);
33
34 // need to support <%# %> expressions
35 item.DataBind();
36 }
37 // add a break between each item
38 this.Controls.Add(new LiteralControl("<br />"));
39 }
40 }
41 return count;
42 }
43 }
That's it! Some points worthy of noting... Line 5 allows the ItemTemplate to be inner content of the SimpleTemplatedControl. Line 6 specifies that the ItemTemplate's container control is SimpleItem. This allows expressions such as Eval or Bind to be properly scoped for databinding. If line 35 was not there - the Eval expression would be ignored.