Microsoft Development NET ASP.NET DataList Dynamic ItemTemplate Controls not firing

wagazub
wagazub used Ask the Experts™
on
I'm new to experts exchange so please forgive protocol errors.

I want to dynamically specify the content of a DataList ItemTemplate. I researched, learnt how to do ITemplate class etc. Still having diffiiculty.Primary issue is that server events for ItemTemplate controls not firing. (Button ID btn in this case.

Code example has 3 files. TemplateTest aspx and cs should be in TemplateTest folder and MovieCollection.cs in App_Code. See aspx
1) DataList1 works fine as expected.
2) Now try to duplicate in DataList2 using code in QPTemplate class. Clicking buttoms does not result in server events firing. DataList2 also is corrupted after server return.

Help much appreciated.

Louis

See TemplateTest.zip

Open in new window

TemplateTest.zip
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Author

Commented:
I've inlined the source files in the code snippet to make this more easy to comment on.

Louis
TemplateTest.ascx
-----------------
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="TemplateTest.aspx.cs" Inherits="TemplateTest_TemplateTest" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
 
 
</head>
<body>
    <form id="form1" runat="server" >
    <div>
        <asp:DataList ID="DataList1" runat="server" DataSourceID="src" >
 
            <ItemTemplate>
                <asp:Button ID="Button1" runat="server" Text='<%# Eval("Name") %>' 
                    onclick="Button1_Click" />            
                Length:
                <asp:Label ID="LengthLabel" runat="server" Text='<%# Eval("Length") %>' />
                <br />
 
            </ItemTemplate>
        </asp:DataList>
        <asp:ObjectDataSource ID="src" runat="server" SelectMethod="GetMovies" 
            TypeName="MovieCollection"></asp:ObjectDataSource>
            
    </div>
    <hr />
    <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
    <hr />
        <div>
        <asp:DataList ID="DataList2" runat="server" DataSourceID="src" >
 
<%--            <ItemTemplate>
                <asp:Button ID="Button1" runat="server" Text='<%# Eval("Name") %>' 
                    onclick="Button1_Click" />            
                Length:
                <asp:Label ID="LengthLabel" runat="server" Text='<%# Eval("Length") %>' />
                <br />
 
            </ItemTemplate>--%>
        </asp:DataList>
           
    </div>
 
    
    </form>
</body>
</html>
 
TemplateTest.aspx.cs
-------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
public partial class TemplateTest_TemplateTest : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        DataList2.ItemTemplate = new QPTemplate(this, this);
    }
    public void Button1_Click(object sender, EventArgs e)
    {
        Label1.Text = "You selected " + ((Button)sender).Text;
    }
 
    public class QPTemplate : ITemplate
    {
        TemplateTest_TemplateTest _caller;
 
        // Will be used in future to dynamically set out template content
        object _futureParameter; 
 
 
        public QPTemplate(TemplateTest_TemplateTest caller, object futureParameter)
        {
 
            _caller = caller;
 
            _futureParameter = futureParameter;
        }
 
        public void InstantiateIn(System.Web.UI.Control container)
        {
            Literal lc = new Literal();
 
            Button ib = new Button();
 
 
            //ib.Click += new EventHandler(ib_Click);
            ib.DataBinding += new EventHandler(Button_DataBinding);
            ib.ID = "btn";
 
            container.Controls.Add(ib);
            Literal lc1 = new Literal();
            lc1.DataBinding += new EventHandler(Literal2_DataBinding);
            container.Controls.Add(lc1);
        }
 
        void ib_Click(object sender, EventArgs e)
        {
            _caller.Button1_Click(sender, e);
        }
 
        private void Literal2_DataBinding(object sender, System.EventArgs e)
        {
 
            Literal lc;
            lc = (Literal)sender;
            DataListItem container = (DataListItem)lc.NamingContainer;
 
            string s = DataBinder.Eval(container.DataItem, "length").ToString();
            lc.Text = "Length: " + s;
            lc.Text += "<br />";
        }
 
        private void Button_DataBinding(object sender, System.EventArgs e)
        {
 
            Button ib;
            ib = (Button)sender;
            DataListItem container = (DataListItem)ib.NamingContainer;
            ib.Text = (string)DataBinder.Eval(container.DataItem, "name");
            ib.Click += new EventHandler(ib_Click);
        }
 
    }
}
 
MovieCollection.cs
------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
 
/// <summary>
/// Summary description for MovieCollection
/// </summary>
public class MovieCollection
{
    public List<Movie> GetMovies()
    {
        List<Movie> movies = new List<Movie>();
        movies.Add(new Movie("Waga", 100));
        movies.Add(new Movie("Gone At All", 120));
        movies.Add(new Movie("Before the Dance", 110));
        movies.Add(new Movie("Homer", 143));
        movies.Add(new Movie("Dancing with Girls", 111));
 
        return movies;
    }
}
 
public class Movie
{
    string _name;
 
    int _length;
 
    public Movie(string Name, int Length)
    {
        _name = Name;
        _length = Length;
    }
 
    public string Name
    {
        get
        {
            return _name;
        }
    }
 
    public int Length
    {
        get
        {
            return _length;
        }
    }
}

Open in new window

Author

Commented:
Points increased
Most Valuable Expert 2012
Top Expert 2008

Commented:
It might be easier if you give me a 1000 meter view, rather than all that detailed information.  What kind of errors are you getting?  How are you binding the DataList?  What kind of page life cycle processing are involved?
Commented:
Solution

After more research the conclusion is

1) Dynamic content is not stored in the VIEWSTATE
2) Hence remove

DataList2.ItemTemplate = new QPTemplate(this, this);

from Page_Load() and put it in the Page_Init() (or DataList2_Init()) event handler. The whole thing works a charm.

p.s. TheLearnedOne. I hoped that the simple specially written minimal example was best way to show problem. Unzip and go to reproduce. What is the best way to include code?

Simple instruction fro what must be a very common requirement.
Most Valuable Expert 2012
Top Expert 2008

Commented:
I don't like looking through other people's code, if I don't have to.  I believe that the question could have been explained well enough to get an answer without code.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial