Scott on Writing

Musings on technical writing...

A Stumper of an ASP.NET Question

Last night a student of mine asked why the Button Web control in a Repeater's ItemTemplate does not raise the Repeater's ItemCommand event when clicked, but a LinkButton does.  I was perplexed because from my understanding anytime a Command event is raised, a CommandEventArgs is bubbled up the control hierarchy.  When the RepeaterItem class detects a bubbled CommandEventArgs, it stops the bubbling of the CommandEventArgs and starts bubbling up a RepeaterCommandEventArgs instance.  Likewise, the Repeater listens for bubbled events, and in detecting a bubbled RepeaterCommandEventArgs, it raises its ItemCommand event.  (This is the same sequence of steps that happens in the DataList and DataGrid.)

I asked this student to show me a code sample where this was the case at a break.  He did and, sure enough, the problem existed as he described.  Specifically, he had a Repeater like so:

<asp:Repeater runat=“server“>
  <ItemTemplate>
    <asp:Button runat=”server” CommandName=”foo” Text=”Button” />
    <asp:LinkButton runat=”server” CommandName=”bar” Text=”LinkButton” />
  </ItemTemplate>
</asp:Repeater>

Next, he created an event handler for the Repeater's ItemCommand event, and did a simple Response.Write() in the event handler.  Finally, in the Page_Load event handler he added the code to bind the data to the Repeater on each postback.  (That is, not just on the first page load...)  Upon visiting the page, if the LinkButton was clicked, the ItemCommand event fired (as evidenced by the Response.Write() output, and by the debugger); clicking the Button, however, did not fire the ItemCommand event.

Clearly, this perplexed me, so I decided to spend some time researching this after class.  The results I have found are very odd and run counter to my understanding of how the Repeater and ASP.NET works.  I am posting this here in hopes that someone will know why this behavior exists.  Let me describe my research.

I started by creating a simple ASP.NET Web page with the following HTML markup:

<asp:Repeater id="Repeater1" runat="server">
  <ItemTemplate>
    <asp:LinkButton ID="linkButtonTest" Runat="server" OnCommand="lCommand" CommandName="bar" Text="LinkButton"></asp:LinkButton>
    <asp:Button OnCommand="bCommand" ID="buttonTest" Runat="server" CommandName="foo" Text="Button"></asp:Button>
    <br />
  </ItemTemplate>
</asp:Repeater>

Next I created a Page_Load event handler and BindData() method that looked like the following:

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        BindData()
    End Sub

    Private Sub BindData()
        Dim a As New ArrayList
        a.Add(1) : a.Add(2) : a.Add(3)
        Repeater1.DataSource = a
        Repeater1.DataBind()
    End Sub

Notice that the data is bound to the Repeater on each and every Page_Load.  If I placed the call to BindData() in Page_Load within an If statement so that it only ran when Not Page.IsPostBack, then the problems described above did not occur.

Following these two methods, I created event handlers for the Button and LinkButton's Command event, as well as an event handler for the Repeater's ItemCommand event.

    Private Sub Repeater1_ItemCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.RepeaterCommandEventArgs) Handles Repeater1.ItemCommand
        Response.Write(String.Concat("<b>ItemCommand</b>: The CommandName = ", e.CommandName, "<br />"))
    End Sub

    Protected Sub bCommand(ByVal sender As Object, ByVal e As CommandEventArgs)
        Response.Write("Button Command event fired!<br />")
    End Sub

    Protected Sub lCommand(ByVal sender As Object, ByVal e As CommandEventArgs)
        Response.Write("LinkButton Command event fired!<br />")
    End Sub

Again, when running this demo the LinkButton, when clicked, would display “LinkButton Command event fired” andItemCommand event fired.”  The Button Web control, however, would only display “Button Command event fired.”  It was apparent that the Button's Command event was indeed firing, but the Repeater's ItemCommand was not.  In an attempt to shed more light onto this I added code in the Command event handlers to print out the control that raised the event (the Button or LinkButton), along with its ancestors in the control hierarchy.  The results stupefied me.  For the LinkButton, the results were as expected:

Control Ascestors: Repeater1:_ctl1:linkButtonTest (System.Web.UI.WebControls.LinkButton) --> Repeater1:_ctl1 (System.Web.UI.WebControls.RepeaterItem) --> Repeater1 (System.Web.UI.WebControls.Repeater) --> _ctl0 (System.Web.UI.HtmlControls.HtmlForm) --> (ASP.test_aspx)

As you can see, the LinkButton was first printed, it's Parent was the RepeaterItem, it's Parent was the Repeater, it's parent was the Web Form, and it's Parent was the ASP.NET Page object.  The Button results, however, were a shock:

Control Ascestors: _ctl0:buttonTest (System.Web.UI.WebControls.Button) --> _ctl0 (System.Web.UI.WebControls.RepeaterItem)

The Button's Parent, as expected, was the RepeaterItem, but the RepeaterItem has no Parent!  This explained why the Repeater's ItemCommand event was not firing - the RepeaterItem could not bubble up the RepeaterCommandEventArgs up to the Repeater to raise the ItemCommand event.  But why isn't there a parent for the RepeaterItem?  The Button's Command event fires after Page_Load, where the control hierarchy is created (via the call to BindData(), which calls the Repeater's DataBind() method).  So the RepeaterItem should indeed have a parent, namely the Repeater!

I decided to create a method to print out the entire control hierarchy.  I then called this method both right after the Repeater was databound and in the Button Command event handler.  The results were as expected: the entire control tree was displayed, showing that the RepeaterItem did indeed have the Repeater as its parent.

 Repeater1 (Parent = _ctl0)
    Repeater1:_ctl0 (Parent = Repeater1)
       Repeater1:_ctl0:_ctl0 (Parent = Repeater1:_ctl0)
       Repeater1:_ctl0:linkButtonTest (Parent = Repeater1:_ctl0)
       Repeater1:_ctl0:_ctl1 (Parent = Repeater1:_ctl0)
       Repeater1:_ctl0:buttonTest (Parent = Repeater1:_ctl0)
       Repeater1:_ctl0:_ctl2 (Parent = Repeater1:_ctl0)
    Repeater1:_ctl1 (Parent = Repeater1)
       Repeater1:_ctl1:_ctl0 (Parent = Repeater1:_ctl1)
       Repeater1:_ctl1:linkButtonTest (Parent = Repeater1:_ctl1)
       Repeater1:_ctl1:_ctl1 (Parent = Repeater1:_ctl1)
       Repeater1:_ctl1:buttonTest (Parent = Repeater1:_ctl1)
       Repeater1:_ctl1:_ctl2 (Parent = Repeater1:_ctl1)
    Repeater1:_ctl2 (Parent = Repeater1)
       Repeater1:_ctl2:_ctl0 (Parent = Repeater1:_ctl2)
       Repeater1:_ctl2:linkButtonTest (Parent = Repeater1:_ctl2)
       Repeater1:_ctl2:_ctl1 (Parent = Repeater1:_ctl2)
       Repeater1:_ctl2:buttonTest (Parent = Repeater1:_ctl2)
       Repeater1:_ctl2:_ctl2 (Parent = Repeater1:_ctl2)

So each of the three RepeaterItems has a Parent in the Button Command event... but it seems like the Button does not have a RepeaterItem with a Parent.  What in the world is happening here?  And why does it work with the LinkButton but not the Button Web control?  Why does it work if the Repeater's DataBind() method was not called on that page visit?  Using Reflector, I've poured over the source code for the Repeater, Button, LinkButton, and Page class, but am at a loss.  Does anyone have any ideas?  Am I missing something simple?

My test case can be viewed online here (includes complete source code).

Thanks for any possible insight...

P.S.: If you can explain why this is happening, and if you're at Tech-Ed this year, I'll buy you a beer!!  :-)

posted on Thursday, May 20, 2004 11:25 AM

Feedback

# re: A Stumper of an ASP.NET Question 5/20/2004 12:56 PM Nick Swan

hi,

alas I'm afraid I can't answer your question but I did just want to say I had the same problem when using a datagrid, and command buttons and hyperlink buttons. I thought I was going mad and had done something really stupid so I'm glad someone else has bought it up!

Cheers
Nick

# re: A Stumper of an ASP.NET Question 5/20/2004 1:05 PM Scott Mitchell

Interesting... from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon/html/vbtskrespondingtobuttoneventsindatalistitems.asp

"If you call the DataBind method of the parent control (the DataList, Repeater, or DataGrid control), the ItemCommand event is not raised, because the contents of the parent control are reset. Therefore, you generally do not want to call the DataBind method on each round trip (that is, in the page initialization without checking for a post back)."

I agree that calling DataBind() on the Repeater "resets" it's Controls collection, but then it builds it back up in the CreateControlHierarchy() method (which is called from the Repeater's DataBind() method). Since it builds the hierarchy back up in the Page_Load, and since the Button's Command event doesn't fire until later in the life-cycle, it still perplexes me as to why the Button doesn't raise the Repeater's ItemCommand event.

Even if we assume that for some magical reason the Button wouldn't raise this event, why does the LinkButton raise the ItemCommand event?

# A Stumper of an ASP.NET Question: SOLVED! 5/20/2004 3:05 PM Scott on Writing

# re: A Stumper of an ASP.NET Question 5/20/2004 3:10 PM Scott Mitchell

This problem has been solved! You can read the details at:
http://scottonwriting.net/sowblog/posts/1268.aspx

# re: A Stumper of an ASP.NET Question 5/20/2004 3:35 PM Jeremy Blosser

I think it has something to do with the Repeater's ViewState messing everything up. If you disable ViewState on the page or repeater control, everything works fine.

Perhaps this will shed some light on the subject. I'm too lazy to use Reflector to track down specifics.

# DataGrid problem that has me stumped! 6/22/2004 6:42 AM Swift Alpha

# re: A Stumper of an ASP.NET Question 10/13/2004 7:24 AM Jonathan Dark

Thanks alot for this, I was having the same problem and you solved it. One weird thing though is that I had a separate solution that I was using to test code before I added it to the complete project solution. In my test solution I had not disabled viewstate and both my button and linkbutton fired their OnItemCommand events. So I copied this exact code over to the project solution and the button did not fire its event. I kept going over the code comparing the two solutions and they were exactly the same, but the test fired and the project did not? Regardless turning off viewstate on the repeater control solved the problem on my project solution, but I have no idea why the test solution worked without having to do so. Anyway just thought I would say thanks and share my experience. Thanks again.

# re: A Stumper of an ASP.NET Question 11/19/2004 2:43 AM oVan

I have the exact same problem: a website on 2 local machines produce this problem, the bit-for-bit exact copy of the site on a remote machine works perfectly.
I don't understand this, and it scares me because there must be something else defining this difference. Maybe some security patch fixed or changed .net dll's? Some machine.config settings?
Anyone?

# re: A Stumper of an ASP.NET Question 11/19/2004 3:00 AM oVan

In fact, the site locally on IE6 doesn't work correctly but in FireFox it does work. Even more strange is that the same site but then remotely with that same IE6 does work!
Aaaaaaaargh! And I can't solve it locally, not even with EnableViewState=False on my datalist.

# re: A Stumper of an ASP.NET Question 11/19/2004 7:29 AM Scott Mitchell

oVan, in the comments you'll see that a solution has been found - see http://scottonwriting.net/sowblog/posts/1268.aspx

# re: A Stumper of an ASP.NET Question 12/24/2004 12:14 AM raj

s

# re: A Stumper of an ASP.NET Question 1/17/2005 3:14 PM Daniel Wellesley

I had a problem with similar symptoms, caused by the datagrid making the viewstate too large for the http post stream too chunk properly - No events would fire (on a page that used to work ok with less data in the database). I found a workaround as outlined at http://tempurisnacks.blogspot.com/2005/01/waste-of-few-days.html

# re: A Stumper of an ASP.NET Question 3/21/2005 6:18 PM obi anyichie

i built a tab strip user control using repeater control template where my tabs are buttons. However i can't get the itemCommand event to fire when i place the tabstrip on my web page. it works fine when i test it alone. i've tried everything from disabling viewstate to binding on every postback...it still doesn't work.

# Databinding issues 4/4/2005 3:59 PM Andrew Hilary

# re: A Stumper of an ASP.NET Question 5/12/2005 7:17 PM Bruce

It seems to me a blanket statement such as this could lead to some coders not using the best tool for the job eg. if you want to display hierarchical info in a datagrid and are using sp's what is wrong with using a dataset returning multiple tables, setting the relations and binding to Denis Bauers hierarchical datagrid. This can be coded much quicker than looped datareaders and is easily extensible by changing the sp called. From my timings in big apps, the time is spent on the query and in a web farm the time is distributed as well. So I agree with Lynn in letting the task decide.
Still its all better than Java :)

# re: A Stumper of an ASP.NET Question 12/2/2005 2:02 AM murthy


I have a Usercontrol in asp.net(c#).
in that i inhereted a repeater control .
that usercontrol used in aspx page.
in that ItemBound is Working but not fire
ItemCommand.

any comments please....

# re: A Stumper of an ASP.NET Question 1/12/2006 8:22 AM b00ger

aaah i had the problem that the ItemCommand wasnt being fired and i was really getting mad until finally i saw this and disabled ViewState...now it all works! i love u all that posted on here :)))))))))

# re: A Stumper of an ASP.NET Question 4/24/2006 7:56 PM Fabian

murthy: Me too, i create a usercontrol and put this control in a itemtemplate.
ItemCommand not work.

# re: A Stumper of an ASP.NET Question 6/20/2006 11:06 AM Paul Maidment

Many thanks to the contibutors on this post, you just saved me a headache, I will file this URL and put it on my blog when I get it running again.

Cheers,
Paul

# re: A Stumper of an ASP.NET Question 6/28/2006 7:32 AM Nick Wood

I have to say that although i agree with everything that's been said in this posting i'm still having problems with my datagrid buttons not raising their event. I'm currently on a project where i need to write 5 pages each utilising a datagrid and associated code. I've basically written 1 page and copied it as a template throughout adding different functionality as i go. Four out of the 5 pages work fine but the 3rd on I copied, although it worked at first, now won't raise the select command event. I've tried disabling viewstate and i'm not databinding on postback....i'm stumped. Double clicking on the datagrid button in designer takes me to the event handler in code ok. I've even deleted the grid and introduced another with a different id and handler, still the same. I could easily scratch this page and just re doit ground up but i'd really loke to know the answer!!

# Scott Mitchell 的ASP.NET 2.0数据教程之三十五:: 使用Repeater和DataList实现的主/从报表 11/23/2006 5:37 AM ISFcn

??:????: Scott Mitchell,????ASP/ASP.NET????,?4GuysFromRolla.com????,?1998??????? ??Web???Scott???????????,???,??,???????Sams????????,24?????ASP.NET 2.0????????mitchell@4guysfromrolla.com,?????????http://ScottOnWriting.NET?????

# re: A Stumper of an ASP.NET Question 11/29/2006 12:57 AM Ruben Cordoba

Given a LinkButton inside a dynamic user control loaded inside a GridView row template, I see LinkButton_Command is never fired. Why?

# Scott Mitchell 的ASP.NET 2.0数据教程之三十五:: 使用Repeater和DataList实现的主/从报表 4/13/2007 12:11 AM wanghr74

Scott Mitchell ?ASP.NET 2.0????????:: ??Repeater?DataList????/???

# Scott Mitchell 的ASP.NET 2.0数据教程之三十五:: 使用Repeater和DataList实现的主/从报表 4/18/2007 4:19 AM heker2007

????

Title:  
Name:  
Url:
Protected by Clearscreen.SharpHIPEnter the code you see:
Comments   

Add To Your Reader

My Links

Archives

Post Categories

 

I am a Microsoft MVP for ASP.NET.
I am an ASPInsider.
<May 2008>
SMTWTFS
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

Comment Stats

DayTotal% of Total
Sunday 1866.8%
Monday 37913.9%
Tuesday 45316.7%
Wednesday 50418.5%
Thursday 53519.7%
Friday 49418.2%
Saturday 1666.1%
Total 2717100.0%

Hour1Total% of Total
12:00 AM 652.4%
1:00 AM 682.5%
2:00 AM 622.3%
3:00 AM 742.7%
4:00 AM 572.1%
5:00 AM 1033.8%
6:00 AM 1084.0%
7:00 AM 1585.8%
8:00 AM 1716.3%
9:00 AM 1475.4%
10:00 AM 1716.3%
11:00 AM 1816.7%
12:00 PM 1886.9%
1:00 PM 1696.2%
2:00 PM 1605.9%
3:00 PM 1324.9%
4:00 PM 1073.9%
5:00 PM 923.4%
6:00 PM 913.3%
7:00 PM 963.5%
8:00 PM 833.1%
9:00 PM 782.9%
10:00 PM 792.9%
11:00 PM 772.8%
Total 2717100.0%

Comments by Blog Entry Date/Time

Day Entry MadeAvg.Total
Sunday 5.54144
Monday 5.22339
Tuesday 4.28419
Wednesday 7.67637
Thursday 6.90607
Friday 5.48411
Saturday 5.33160
Total 5.842717

Hour1 Entry MadeAvg.Total
12:00 AM 5.0035
1:00 AM 1.002
5:00 AM 0.000
7:00 AM 7.0035
8:00 AM 5.35107
9:00 AM 6.32278
10:00 AM 6.47246
11:00 AM 4.41181
12:00 PM 6.88330
1:00 PM 3.00111
2:00 PM 5.41222
3:00 PM 8.64285
4:00 PM 4.0589
5:00 PM 5.92154
6:00 PM 4.52113
7:00 PM 9.67174
8:00 PM 9.80147
9:00 PM 5.05111
10:00 PM 5.4265
11:00 PM 4.5732
Total 5.842717

Learn More About Comment Stats
1 - All times GMT -8...


Blog Stats

Favorite Web Sites

My Books

My MSDN Articles