Creating A Custom DataBound Templated Control In ASP.NET 2.0
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.