You are here:About>Computing & Technology>Delphi Programming
About.comDelphi Programming
Binding the DataList ASP.NET Control with Dynamic Templates
Learn how to programmatically implement the ITemplate interface to dynamically create the ItemTemplate content for a DataList Web Server control.
 Source Code
• Download Source Code
 Join the Discussion
"Post your views and comments to this chapter of the free Asp.Net Delphi Programming Course"
Discuss!
 Related Resources
• A Beginner's Guide to Asp.Net Programming for Delphi developers.TOC

Welcome to the 22nd chapter of the FREE online programming course:
A Beginner's Guide to Asp.Net Programming for Delphi developers.
Implementing the ITemplate interface to programmatically create data bound list control templates.

Back in the last few chapters, we've looked at several different approaches to data binding in ASP.NET web applications: binding list controls, using binding expressions and binding the Repeater control (the most lightweight of all data bound list controls).

Throughout this chapter, you'll learn about the following:

  • DataList Web Server control
  • ITemplate interface (defining programmatically)
  • NamingContainer
  • DataList Web Server Control
    The DataList offers a richer feature set than the Repeater, including automatic generation of <table>, <tr> and <td> tags (optional) to hold each list item. DataList also requires that you create templates to define the content and layout of each item.
    DataList supports 7 different templates. Beside those found in the Repeater, the DataList also provides the SelectedItemTemplate and the EditItemTemplate - to allow selecting and editing of items.
    Editing and selecting in data bound list controls will be discussed when we introduce the DataGrid control.

    The layout of the DataList control is controlled with the RepeatLayout property. Setting this property to RepeatLayout.Table will display the DataList in a table format, while RepeatLayout.Flow displays the DataList without a table structure.
    Similar to the Repeater, the DataList, at the very minimum, needs the ItemTemplate to be defined to display "its" items.

    When you drop a DataList control on a web page, at design time, you'll get the following:

    DataList at design time
    As the initial design time rendering of the DataList suggest, you need to specify at least the ItemTemplate for the list.

    Delphi allows you to specify some of the templates visually. Right click the DataList and select "Header and Footer Templates" from the drop down list, to edit the templates.

    Templates at design time

    Add a hyperlink to the Footer Template (assign both the Text and the NavigateUrl properties), and a "string" to the Header Template.

    DataList HeaderTemplate and FooterTemplate

    Select "End Template Editing" from the right-click menu.

    Note that the design time rendering of the control has not changed, however when you switch to the "aspx/html" view the asp markup will be:

    <asp:DataList id="DataList1" runat="server">
    <HeaderTemplate>
      About Delphi Programming
    </HeaderTemplate>
    <FooterTemplate>
      <asp:HyperLink 
         id="HyperLink1" 
         runat="server"
         navigateurl="http://delphi.about.com">
      delphi.about.com
      </asp:HyperLink>
    </FooterTemplate>
    </asp:DataList>
    

    Note: if you run the project now, you'll get an "empty" page at run time (rendered to the user in a Web Browser). DataList will not render if the DataBind method is not called.

    The DataSource
    For the sake of simplicity I'll use an ArrayList variable to hold the list of custom TArticle objects that will be displayed by the DataList:

    TArticle = class
    private
      FTitle : string;
      FUrl : string;
    public
      property Title : string read FTitle;
      property URL : string read FUrl;
    
      constructor Create(const title, url : string);
    end;
    

    The Page will have a property Articles (ArrayList of TArticle objects).

    Here's how the Page_Load event should look:

    procedure TwfDataListTemplates.Page_Load(
      sender: System.Object; 
      e: System.EventArgs);
    begin
      DataList1.ItemTemplate := TDataListItemTemplate.Create;
    
      if NOT Page.IsPostBack then
      begin
        FillArticles;
    
        DataList1.DataSource := Articles;
        DataList1.DataBind;
      end;
    end;
    

    The "FillArticles" method simply places some TArticle objects in the Articles property:

    procedure TwfDataListTemplates.FillArticles;
    begin
      Articles.Add(TArticle.Create(
          'Display Menu Item Hints',
          '/od/vclusing/a/menuitemhints.htm'));
      Articles.Add(TArticle.Create(
          'Move and Resize Controls at Run Time',
          '/library/weekly/aa102505a.htm'));
      Articles.Add(TArticle.Create(
          'Memory Leaks in Delphi Applications',
          '/od/oopindelphi/a/memoryleak.htm'));
    end;
    

    Note that while the DataSource property is assigned and the DataBind method is called - at run time - no items will be renderd! Reason? We haven't specified the ItemTemplate!

    Take a time to look at the resulting HTML:

    <table id="DataList1" cellspacing="0" border="0" 
           style="border-collapse:collapse;">
    <tr>
      <td>About Delphi Programming</td>
    </tr>
    <tr>
      <td></td>
    </tr><tr>
      <td></td>
    </tr><tr>
      <td></td>
    </tr><tr>
    	<td>
        <a id="DataList1__ctl4_HyperLink1" 
         href="http://delphi.about.com">delphi.about.com</a>
      </td>
    </tr>
    </table>
    

    The "About Delphi Programming" string is what we placed in the Header Template. The "<a id="DataList1__ctl4_HyperLink1" href="http://delphi.about.com">delphi.about.com</a>" is the HyperLink control we added to the FooterTemplate.
    Finally, there are 3 empty rows each having 2 empty cells! Note that the "Articles" property has 3 items and that each article has two properties. But, the content is not rendered.

    Since I've already explained how to create a sample ItemTemplate (declaratively inside the control's markup tags) for the Repeater control and how DataSource and DataBind (and the DataBinder class) are used - this time I'll show you how to create one of the templates programmatically.

    Implementing the ITemplate Interface
    To create any of the templates programmatically a custom class needs to implement the ITemplate interface. ITemplate has only one procedure, InstantiateIn, which receives a Control parameter. The control passed to InstantiateIn defines the Control object to which child controls in the template will be parented. Here's the full source of a custom class implmenting the ITemplate interface.

    TDataListItemTemplate = class(System.Object, ITemplate)
    public
      procedure InstantiateIn(container: Control);
      procedure ItemBinding (Sender : TObject; e:EventArgs);
    end;
    ...
    procedure TDataListItemTemplate.InstantiateIn(
      container: Control);
    var
      ph : PlaceHolder;
      hl : HyperLink;
    begin
      ph := PlaceHolder.Create;
    
      hl := HyperLink.Create;
    
      ph.Controls.Add(hl);
    
      Include(ph.DataBinding, ItemBinding);
    
      container.Controls.Add(ph);
    end; (*InstantiateIn*)
    
    procedure TDataListItemTemplate.ItemBinding(
      Sender: TObject; 
      e: EventArgs);
    const
      ADPUrl = 'http://delphi.about.com';
    var
      ph : PlaceHolder;
      hl : HyperLink;
      container : DataListItem;
    begin
      ph := Sender as PlaceHolder;
      container := ph.NamingContainer as DataListItem;
    
      hl := ph.Controls[0] as HyperLink;
    
      hl.Text := TArticle(container.DataItem).Title;
      hl.NavigateUrl := ADPUrl+TArticle(container.DataItem).URL;
      
    end; (*ItemBinding*)
    

    The InstantiateIn procedure creates and adds controls to the specified container control. If data binding is required on any of these controls, the DataBinding event must be hooked up.

    I decided to use the PlaceHolder control as it provides no rendering of its own and can be used as a container. A HyperLink control is created and placed "inside" the PlaceHolder.
    As already explained, when a control is binded (DataBind is called for the control) - all the child controls are also binded. A DataBinding handler is needed for each control that would require DataBinder.Eval in the inline template. With this in mind, we only need to handle the DataBinding event of the PlaceHolder - all the child controls can be bound to some value in this single event handler.

    DataBinding even handler explained
    A custom ItemBinding handles the DataBinding event. The sender parameter is the control on behalf of which you're handling the DataBinding event (PlaceHolder). The NamingContainer property of the sender indicates the nearest control that implements INamingContainer. The nearest container for a child control generated within a DataList's item is the DataListitem object of the corresponding item. Getting this reference is essential, as it is the only way to access the bound data.

    Once we lay our hands on the DataItem, by simply casting it to the correct class (TArticle) we can assign values to properties of the HyperLink control created in the InstantiateIn implementation.

    Note: while this looks messy, it's quite straight-forward ... just follow the code :)

    Finally, the page rendered to the user:

    DataList in Browser

    Download the full source to explore. Also, try playing with various properties of the DataList.

    To the next chapter: A Beginner's Guide to ASP.NET Programming for Delphi developers
    That's it for today. In the next chapter we'll continue exploring the topic of data binding in ASP.NET.

    If you need any kind of help at this point, please post to the Delphi Programming Forum where all the questions are answered and beginners are treated as experts.

    A Beginner's Guide to ASP.NET Programming for Delphi developers: Next Chapter >>
    >> Developing and Using Custom User Controls in ASP.NET

    From Zarko Gajic,
    Your Guide to Delphi Programming.
    FREE Newsletter. Sign Up Now!
    Newsletters & RSSEmail to a friendSubmit to Digg
     All Topics | Email Article | | |
    Advertising Info | News & Events | Work at About | SiteMap | Reprints | HelpOur Story | Be a Guide
    User Agreement | Ethics Policy | Patent Info. | Privacy Policy©2008 About, Inc., A part of The New York Times Company. All rights reserved.