Re: The Command event of dynamically loaded controls

From: Donald Xie (donald_xie_at_msdn.nospam)
Date: 02/02/04


Date: Mon, 2 Feb 2004 13:15:44 +0800

Thanks for the excellent explanation, Mike. Yes that answers my question.

Now I'm trying to find a good solution for my problem. In a nutshell, I need
to load a hierarchical list of folders and files from a database and display
them on a tree - very much the same as the MSDN Library deeptree.asp. The
number of nodes is potentially large, so I'll only load all top level
folders plus folders in the branch selected by the user. Only one branch can
be expanded each time. My users can click a folder node to expand or
collapse it, based on the selected folder's state.

Since my client doesn't want to use a third party tree control, my first
thought i\was to programmatically create a list of ImageButton/LinkButton
pairs to display the folders. This dynamic control's behavior means that:

1. I'll need to load the folder list in the first pass to wire up the
controls and corresponding event handlers. After it's loaded, the event
handler will fire and give me the selected folder. Then,

2. I'll then load the folder list again with the selected folder
expanded/collapsed.

It doesn't seem like a very efficient solution now because it requires two
trips to the database to load the folder list. Caching doesn't sound very
attractive either because list can be quite big and changes frequently.

Any suggestions are very much appreciated.

Cheers,
Donald Xie

""Mike Moore [MSFT]"" <michmo@online.microsoft.com> wrote in message
news:AXcHok55DHA.3032@cpmsftngxa07.phx.gbl...
> Hi Donald,
>
> This is normal behavior and results from the way ASP.NET remembers the old
> value for that text box in order to determine if the new value is
different.
>
> Each time the form is sent to the browser, ASP.NET stores the current text
> box value (and other controls) in a hidden field which it sends to the
> browser. When the browser posts the page back, the hidden field is sent to
> the server along with the rest of the form. ASP.NET parses the list of old
> values from the hidden field and attempts to associate each value with a
> control. Then it compares the new value of the control with the old value
> and triggers events.
>
> The text box must be recreated to allow ASP.NET to associate it with the
> old value from the hidden field. Only then can ASP.NET compare the new and
> old values.
>
> Here is a code sample which demonstrates one text box that correctly
> triggers the changed event and three text boxes which fail for each of
> three reasons.
>
>
> **** HTML
> <form id="Form1" method="post" runat="server">
> <P>This sample contains a series of text boxes added to the page<BR>
> programmatically with Controls.Add. The variations in these<BR>
> text boxes demonstrate how to (and how not to) add a control<BR>
> so that it can fire an event.<BR>
> <BR>
> </P>
> <asp:panel id="Panel1" runat="server">
> <P>
> <asp:Label id="Label5" runat="server" Width="115px"> With
> ViewState:</asp:Label>
> <asp:PlaceHolder id="PlaceHolder1"
> runat="server"></asp:PlaceHolder>&nbsp;
> <asp:Label id="Label1" runat="server" Width="368px"
> EnableViewState="False"></asp:Label></P>
> <P>
> <asp:Label id="Label6" runat="server" Width="115px" Height="19"> No
> ViewState:</asp:Label>
> <asp:PlaceHolder id="PlaceHolder2"
> runat="server"></asp:PlaceHolder>&nbsp;
> <asp:Label id="Label2" runat="server" Width="368px"
> EnableViewState="False"></asp:Label></P>
> <P>
> <asp:Label id="Label7" runat="server" Width="115px"
> Height="19px">Controls.AddAt:</asp:Label>
> <asp:Label id="Label3" runat="server" Width="368px"
> EnableViewState="False"></asp:Label></P>
> <P>
> <asp:Label id="Label8" runat="server" Width="115px"
> Height="19px">!IsPostBack:</asp:Label>
> <asp:PlaceHolder id="PlaceHolder4"
> runat="server"></asp:PlaceHolder>&nbsp;
> <asp:Label id="Label4" runat="server" Width="368px"
> EnableViewState="False"></asp:Label></P>
> </asp:panel>
> <P><asp:button id="Button1" runat="server" Text="Submit" Width="100px"
> Height="27px"></asp:button></P>
> <P><hr></P>
> <P>As you can see through experimenting with the above, the text<BR>
> box labeled "With ViewState" is the only one that works
properly.<BR>
> <BR>
> The "No ViewState" and the "Controls.AddAt" text boxes both<BR>
> fire their changed events whenever they contain text, even if
that<BR>
> text has not changed.<BR>
> <BR>
> The "!IsPostBack" text box simply disappears upon postback.</P>
> </form>
>
>
> **** CODE
> private void Page_Load(object sender, System.EventArgs e)
> {
> System.Web.UI.WebControls.TextBox MyTextBox;
>
> MyTextBox = new TextBox();
> MyTextBox.ID = "TextBox1";
> MyTextBox.EnableViewState=true;
> PlaceHolder1.Controls.Add(MyTextBox);
> MyTextBox.TextChanged += new
> System.EventHandler(this.TextBox_TextChanged);
>
> MyTextBox = new TextBox();
> MyTextBox.ID = "TextBox2";
> MyTextBox.EnableViewState=false;
> PlaceHolder2.Controls.Add(MyTextBox);
> MyTextBox.TextChanged += new
> System.EventHandler(this.TextBox_TextChanged);
>
> MyTextBox = new TextBox();
> MyTextBox.ID = "TextBox3";
> MyTextBox.EnableViewState=true;
> Panel1.Controls.AddAt(15,MyTextBox);
> MyTextBox.TextChanged += new
> System.EventHandler(this.TextBox_TextChanged);
>
> if(!IsPostBack)
> {
> MyTextBox = new TextBox();
> MyTextBox.ID = "TextBox4";
> MyTextBox.EnableViewState=true;
> PlaceHolder4.Controls.Add(MyTextBox);
> MyTextBox.TextChanged += new
> System.EventHandler(this.TextBox_TextChanged);
> }
> }
>
> private void TextBox_TextChanged(object sender, System.EventArgs e)
> {
> TextBox txtBoxSender = (TextBox)sender;
> string strTextBoxID = txtBoxSender.ID;
>
> switch(strTextBoxID)
> {
> case "TextBox1":
> Label1.Text = "Changed";
> break;
> case "TextBox2":
> Label2.Text = "Changed";
> break;
> case "TextBox3":
> Label3.Text = "Changed";
> break;
> case "TextBox4":
> Label4.Text = "Changed";
> break;
> }
> }
>
>
> ---
> Please see these articles for more information.
>
> Adding Controls to a Web Forms Page Programmatically
>
http://msdn.microsoft.com/library/en-us/vbcon/html/vbtskaddingcontrolstowebf
> ormspageprogrammatically.asp
>
> HOW TO: Dynamically Create Controls in ASP.NET by Using Visual C# .NET
> http://support.microsoft.com/default.aspx?scid=kb;EN-US;317794
>
> Does this answer your question?
>
> Thank you, Mike
> Microsoft, ASP.NET Support Professional
>
> Microsoft highly recommends to all of our customers that they visit the
> http://www.microsoft.com/protect site and perform the three
straightforward
> steps listed to improve your computer’s security.
>
> This posting is provided "AS IS", with no warranties, and confers no
rights.
>
>
> --------------------
> > From: "Donald Xie" <donald_xie@msdn.nospam>
> > Subject: The Command event of dynamically loaded controls
> > Date: Fri, 30 Jan 2004 16:52:00 +0800
> > Lines: 54
> > X-Priority: 3
> > X-MSMail-Priority: Normal
> > X-Newsreader: Microsoft Outlook Express 6.00.2800.1158
> > X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165
> > Message-ID: <#C2U35w5DHA.2580@TK2MSFTNGP11.phx.gbl>
> > Newsgroups: microsoft.public.dotnet.framework.aspnet
> > NNTP-Posting-Host: 202.181.80.84
> > Path:
>
cpmsftngxa07.phx.gbl!cpmsftngxa10.phx.gbl!TK2MSFTNGXA05.phx.gbl!TK2MSFTNGP08
> phx.gbl!TK2MSFTNGP11.phx.gbl
> > Xref: cpmsftngxa07.phx.gbl
microsoft.public.dotnet.framework.aspnet:206364
> > X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet
> >
> > Hi,
> >
> > I noticed an interesting effect when working with controls that are
> > dynamically loaded. For instance, on a web form with a PlaceHolder
control
> > named ImageHolder, I dynamically add an image button at runtime:
> >
> > //----- Code snippet
> > protected System.Web.UI.WebControls.PlaceHolder ImageHolder;
> >
> > private void Page_Load(object sender, System.EventArgs e)
> > {
> > if (!IsPostBack)
> > LoadDynamicImageButton();
> > }
> >
> > private void ImageButton_Click(object sender,
> > System.Web.UI.ImageClickEventArgs e)
> > {
> > Response.Write("Image button clicked");
> > }
> >
> > private void LoadDynamicImageButton()
> > {
> > ImageButton btn = new ImageButton();
> > btn.ImageUrl = "Images/Minus.png";
> > btn.Click += new ImageClickEventHandler(ImageButton_Click);
> > ImageHolder.Controls.Add(btn);
> > }
> > //----- End code snippet
> >
> > The first time the page loads, the image button is created. When I click
> it,
> > it reloads the page but doesn't trigger its ImageClickEventHandler. If I
> > forcefully run LoadDynamicImageButton(), i.e., remove the IsPostBack
check
> > in Page_Load() to recreate the image, its ImageClickEventHandler is
> > triggered. This happens with the Command event as well.
> >
> > It seems that on post-back, if a dynamically loaded control is not
loaded,
> > then its event handler is not wired. Its properties such as CommandName
> and
> > CommandArgument, OTOH, persists from the last load.
> >
> > The problem is that if I dynamically load up the PlaceHolder control
with
> > different controls according to the button clicked, this behavior forces
> all
> > those controls to be loaded twice - first to load all default controls
> just
> > to wire up their event handlers, then to reload them again according to
> the
> > event. There are also other factors, such as the assigning a differnet
> > ImageUrl, that seem to affect whether or not the event handler is
> triggered.
> > I'm still working on it to hopefully isolate the problem.
> >
> > Is there a workaround?
> >
> > Thanks,
> > Donald Xie
> >
> >
> >
>


Loading