PDA

View Full Version : ParseControl() method problem


clsimeone
12-15-2003, 07:03 AM
Hello,

I'm having problems with the ParseControl() method creating unexpected
output which I think is preventing events from firing.

My code is based on this MSDN article:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebuitemplatecontrolclassparsecontrolto pic.asp

The C# section of this simple example shows using ParseControl with an
asp:button as follows:

void Page_Load(object sender, System.EventArgs e)
{
Control c = ParseControl("<asp:button text='Click here!'
runat='server' />");
myPlaceholder.Controls.Add(c);
}

This works for me until I add additional parameters.

Below is my C# code, the ASPX file and the rendered HTML. When looking
at the rendered HTML notice the difference between the controls added
to the aspx file (Button0 and Button1) and the html rendered by the
ParseControl method (Button3 and Button4).

Notice the "oncommand" parameter on the html rendered by ParseControl
(Button3 and Button4). I think this is what breaks my code.

When clicking on Button0 or Button1 an event is fired. But, the
buttons rendered by ParseControl do not fire any events.

Am I doing something wrong? Is this a bug? Any help would be greatly
appreciated.

Thanks,
Chris S.


========
C# Code
========

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

...

public class ParseControl : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Label Label1;
protected System.Web.UI.WebControls.PlaceHolder myPlaceHolder;

void Page_Load(object sender, System.EventArgs e)
{
Control c3 = ParseControl("<asp:button id='Button3'
text='Btn3'
oncommand='OnButton'
commandname='Btn'
commandargument='b3'
runat='server' />");

Control c4 = ParseControl("<asp:button id='Button4'
text='Btn4'
oncommand='OnButton'
commandname='Btn'
commandargument='b4'
runat='server' />");

myPlaceHolder.Controls.Add(c3);
myPlaceHolder.Controls.Add(c4);
}

public void OnButton(Object Sender, CommandEventArgs e)
{
switch (e.CommandArgument.ToString().ToLower())
{
case "b0":
Label1.Text = "Button 0";
break;
case "b1":
Label1.Text = "Button 1";
break;
};
}
}

...

=========
ASPX File
=========

<%@ Page Language="c#" CodeBehind="ParseControl.aspx.cs"
AutoEventWireup="false" Inherits="Learn.ParseControl" %>

<html>
[b]
<form id="Form1" runat="server" >
<h3>PlaceHolder Example</h3>

<p><asplaceholder id="myPlaceHolder" runat="server" /></p>

<asp:button id='Button0'
text='Btn0'
oncommand='OnButton'
commandname='Btn'
commandargument='b0'
runat='server' />

<asp:button id='Button1'
text='Btn1'
oncommand='OnButton'
commandname='Btn'
commandargument='b1'
runat='server' />

<p><asp:Label id="Label1" runat="server">Label</asp:Label></p>
</form>
</body>
</html>


============
Rendered HTML
============

<html>
[b]
<form name="Form1" method="post" action="ParseControl.aspx"
id="Form1">
<input type="hidden" name="__VIEWSTATE"
value="dDwxMDM1NjY1MjU7Oz4+z8z1xQCw84hCCjmMrZwjvAz43A==" />

<h3>PlaceHolder Example</h3>

<p>
<input type="submit" name="Button3" value="Btn3" id="Button3"
oncommand="OnButton" />
<input type="submit" name="Button4" value="Btn4" id="Button4"
oncommand="OnButton" />
</p>

<input type="submit" name="Button0" value="Btn0" id="Button0" />
<input type="submit" name="Button1" value="Btn1" id="Button1" />

<p><span id="Label1">Label</span></p>
</form>
</body>
</html>

pjoyce
12-28-2003, 05:12 AM
I haven't tried this myself, but what I suspect is that you aren't wiring the events up. When you create control programatically you have to wire up the events yourself. So take a look at the code generated under "Web Form Designer Generated Code" in the InitializeComponent() method. You'll see this.btn0.click += new SystemEventHandler(...). Do the same thing in your PageLoad() after you create c3 and c4. You will have to cast the controls to type button. Actually you chould just initially create them as type button. Then you have to create handlers for the Click events.

Let me know if this doens't make sense, I wil go into greater detail.

cheers!
[b]quote:Originally posted by clsimeone

Hello,

I'm having problems with the ParseControl() method creating unexpected
output which I think is preventing events from firing.

My code is based on this MSDN article:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebuitemplatecontrolclassparsecontrolto pic.asp
</blockquote id="quote"></font id="quote">

clsimeone
12-31-2003, 07:36 AM
Hi PJoyce

Thanks for your reply. That makes perfect sense to me now.

What I'm actually trying to do is create dynamic menus using XML/XSLTs and let the XSLT spit out the ParseControl. It's going to be tricky to figure this one out.

Thanks Again,
Chris

simon
01-19-2004, 11:28 AM
Hi all,

I got the runtime error on casting the System.Web.UI.Control to System.Web.UI.WebControls.Button. Does anyone know the reason?

..

Button c = (Button)Page.ParseControl("<asp:button text='Click here!' runat='server' />");
..

Regards

Simon

pjoyce
01-21-2004, 08:08 AM
Okay, I did a little investigation on ParseControl() because your post was the first I saw of it. I don't think it's what you want. It seems more oriented toward creating custom designers for custom controls. I think you might be over-thinking the problem. What you really want to do is just create a button control, set the properties and add it to the placeholder.

Below is what I would do for your PageLoad():

[quote]
privatevoidPage_Load(objectsender,System.EventArgs e){

Buttonc3=newButton();
c3.Text="Btn3";
c3.Command+=newSystem.Web.UI.WebControls.CommandEv entHandler(OnButton);
c3.CommandArgument="b0";
myPlaceHolder.Controls.Add(c3);

Buttonc4=newButton();
c4.Text="Btn4";
c4.Command+=newSystem.Web.UI.WebControls.CommandEv entHandler(OnButton);
c4.CommandArgument="b1";
myPlaceHolder.Controls.Add(c4);
}
</CODE>

Also, I would make OnButton private rather than public. It doesn't need to be public.
[b]quote:Originally posted by simon

Hi all,

I got the runtime error on casting the System.Web.UI.Control to System.Web.UI.WebControls.Button. Does anyone know the reason?

..

Button c = (Button)Page.ParseControl("<asp:button text='Click here!' runat='server' />");
..

Regards

Simon

</blockquote id="quote"></font id="quote">

nkimber
11-07-2006, 10:00 AM
I had the same problem. I am planning to write our application framework so that I can have a single CodeBehind linked to by multiple custom User Controls. This way, the layout for each client can be completely different, but the functionality for each control is exactly the same. I don't want to have actually dump .ascx files all over my website as this is a pain and I want to be able to control content layout without releasing new files to the website.
My solution is to use the ParseControl() method as you have been trying to use.
The secret is that ParseControl does return a Control object, but it does not return a Parsed Control object. Your text that is being sent to the ParseControl method could contain 10 ASP controls. So, ParseControl returns a Control object that has all of the ParsedControls within its Controls collection.

If you look in the Controls collection you will be able to find a reference to your dynamically created button.
Other points to note here, you cannot find the control using the ID and FindControl() method until the controls have been added to your page/control object.
Also, with respect to wiring the events, you are responsible for doing this by hand.

It's not that bad, as in fact an incredibly flexible approach to being to drastically customise different client presentations declaritively. You simply end up with a list of control IDs and their corresponding code behind events.