Programmatic Dropdown and SelectedIndexChanged event

J

J055

Hi

I have a dropdown control which is constructed in another dropdown control
SelectedIndexChanged event

protected void ddlParamType_SelectedIndexChanged(object sender, EventArgs e)
{
// some other code
DropDownList ddlGroups = new DropDownList();
ddlGroups.SelectedIndexChanged += new
EventHandler(this.ddlGroups_SelectedIndexChanged);
// binding etc.
}

When the new constructed dropdown is posted back the SelectedIndexChanged
event does not call the ddlGroups_SelectedIndexChanged method. Once the
method is called I don't need the control anymore. What is the best practice
to follow?

Thanks
Andrew
 
W

Walter Wang [MSFT]

Hi Andrew,

To make ASP.NET fire the ddlGroups_SelectedIndexChanged event, you have to
make sure the dynamically created DropDownList exist in the control
hierarchy when the page is postback. Since the DropDownList is only created
in the first DropDownList's SelectedIndexChanged event, it's not re-created
upon the second postback caused by other user action.

To fix it, you can use several options.

1) Use a viewstate variable to flag whether we need the second DropDownList
or not, then re-create it in Page_Load if needed. This will make sure the
event get's fired correctly.

protected void Page_Load(object sender, EventArgs e)
{
if (NeedDropDownList)
{
CreateDropDownList(true);
}
}

protected void CreateDropDownList(bool flag)
{
const string THE_ID = "ddl2";
if (flag)
{
DropDownList ddl2 = new DropDownList();
ddl2.SelectedIndexChanged += new
EventHandler(ddl2_SelectedIndexChanged);
ddl2.ID = THE_ID;
ddl2.AutoPostBack = true;
ddl2.Items.Add(new ListItem("1", "value1"));
ddl2.Items.Add(new ListItem("2", "value2"));
form1.Controls.Add(ddl2);
}
else
{
form1.Controls.Remove(form1.FindControl(THE_ID));
}
NeedDropDownList = flag;
}

void ddl2_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList ddl2 = sender as DropDownList;
Response.Write(ddl2.SelectedValue);
CreateDropDownList(false);
}

protected bool NeedDropDownList
{
get
{
object o = ViewState["A"];
if (o == null) return false;
return (bool)o;
}
set { ViewState["A"] = value; }
}

protected void DropDownList1_SelectedIndexChanged(object sender,
EventArgs e)
{
CreateDropDownList(true);
}


2) Since in this case the DropDownList's SelectedIndexChanged event is
simple, all you wanted is the selected item's text or value, therefore I
think you don't need the event at all, just check the Request.Form
collection to see if it's there.

protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
object o = Request.Form["ddl2"];
if (o != null)
{
Response.Write(o);
}
}
}

protected void DropDownList1_SelectedIndexChanged(object sender,
EventArgs e)
{
DropDownList ddl2 = new DropDownList();
ddl2.ID = "ddl2";
ddl2.AutoPostBack = true;
ddl2.Items.Add(new ListItem("1", "value1"));
ddl2.Items.Add(new ListItem("2", "value2"));
form1.Controls.Add(ddl2);
}


Please note this second approach do have one difference with the first
approach: if the postback is caused by other controls (for example: a
button's click) after the second dropdownlist is created dynamically, in
Page_Load you will still find the ddl2's value in Request.Form regardless
if the selected index is changed or not. In the first approach, the
SelectedIndexChanged event of the second dropdownlist only fires when the
index is really changed.


Hope this helps.


Sincerely,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications. If you are using Outlook Express, please make sure you clear the
check box "Tools/Options/Read: Get 300 headers at a time" to see your reply
promptly.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
J

J055

Hi Walter, thanks for this

I think the first example looks better. My DropDownList is added to a
RepeaterItem. There can only be one at a time for each postback. If I
created the control in the Page_Load event then I don't which RepeaterItem
needs the control I think. Can I add it in the Repeater ItemCreated event?
If so How should I do this? I have a lot of problems working out how to
share information between events and how to find controls when dealing with
Lots of controls and nested repeaters and where the page has a master page,
header and footer etc. Can you also point me to some useful articles and
documentation if you think it will help me?

Thanks
Andrew



Walter Wang said:
Hi Andrew,

To make ASP.NET fire the ddlGroups_SelectedIndexChanged event, you have to
make sure the dynamically created DropDownList exist in the control
hierarchy when the page is postback. Since the DropDownList is only
created
in the first DropDownList's SelectedIndexChanged event, it's not
re-created
upon the second postback caused by other user action.

To fix it, you can use several options.

1) Use a viewstate variable to flag whether we need the second
DropDownList
or not, then re-create it in Page_Load if needed. This will make sure the
event get's fired correctly.

protected void Page_Load(object sender, EventArgs e)
{
if (NeedDropDownList)
{
CreateDropDownList(true);
}
}

protected void CreateDropDownList(bool flag)
{
const string THE_ID = "ddl2";
if (flag)
{
DropDownList ddl2 = new DropDownList();
ddl2.SelectedIndexChanged += new
EventHandler(ddl2_SelectedIndexChanged);
ddl2.ID = THE_ID;
ddl2.AutoPostBack = true;
ddl2.Items.Add(new ListItem("1", "value1"));
ddl2.Items.Add(new ListItem("2", "value2"));
form1.Controls.Add(ddl2);
}
else
{
form1.Controls.Remove(form1.FindControl(THE_ID));
}
NeedDropDownList = flag;
}

void ddl2_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList ddl2 = sender as DropDownList;
Response.Write(ddl2.SelectedValue);
CreateDropDownList(false);
}

protected bool NeedDropDownList
{
get
{
object o = ViewState["A"];
if (o == null) return false;
return (bool)o;
}
set { ViewState["A"] = value; }
}

protected void DropDownList1_SelectedIndexChanged(object sender,
EventArgs e)
{
CreateDropDownList(true);
}


2) Since in this case the DropDownList's SelectedIndexChanged event is
simple, all you wanted is the selected item's text or value, therefore I
think you don't need the event at all, just check the Request.Form
collection to see if it's there.

protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
object o = Request.Form["ddl2"];
if (o != null)
{
Response.Write(o);
}
}
}

protected void DropDownList1_SelectedIndexChanged(object sender,
EventArgs e)
{
DropDownList ddl2 = new DropDownList();
ddl2.ID = "ddl2";
ddl2.AutoPostBack = true;
ddl2.Items.Add(new ListItem("1", "value1"));
ddl2.Items.Add(new ListItem("2", "value2"));
form1.Controls.Add(ddl2);
}


Please note this second approach do have one difference with the first
approach: if the postback is caused by other controls (for example: a
button's click) after the second dropdownlist is created dynamically, in
Page_Load you will still find the ddl2's value in Request.Form regardless
if the selected index is changed or not. In the first approach, the
SelectedIndexChanged event of the second dropdownlist only fires when the
index is really changed.


Hope this helps.


Sincerely,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications. If you are using Outlook Express, please make sure you clear the
check box "Tools/Options/Read: Get 300 headers at a time" to see your
reply
promptly.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no
rights.
 
W

Walter Wang [MSFT]

Hi Andrew,

Would you please tell me more about your specific requirement or design?
This way I can provide more specific suggestion. Thanks.

Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
J

J055

Hi Walter

Thanks for the response.

The second DropDownList control is optionally created in each dynamic row of
a Repeater so I don't think I can know how many DDL controls should be
created in the Page_Load event, e.g.

protected void CreateGroupsSetsDropDownList(TableRow row, bool flag)
{
if (flag)
{
DropDownList ddlGroups = new DropDownList();
ddlGroups.SelectedIndexChanged += new
EventHandler(this.ddlGroupSets_SelectedIndexChanged);
//do binding
row.Cells[1].Controls.Add(ddlGroups);
}
else
{
}
NeedDropDownList = flag;
}

The ddlGroupSets_SelectedIndexChanged is also used by controls which are
created at runtime already, i.e. not on demand from a user action. So I want
to try to use this for the dynamically created control.

In the Page_Load event I need to know all potential rows required for the
DroupDownList and remove all controls from the CreateGroupsSetsDropDownList
method which not required. I guess I need to know which row in the Repeater
is flaged as NeadDropDownList.

Please let me know if I've provided enough information for you.
Thanks
Andrew
 
W

Walter Wang [MSFT]

Hi J055,

Thanks for the explanation. Based on my understanding:

1) you're binding the Repeater to some data source only when the page first
loads
2) in Repeater's ItemDataBound event, you will optionally create a
DropDownList in the item based on some flag
3) the dynamically DropDownList will be removed after it's used, i.e.,
removed in its SelectedIndexChanged event, otherwise they should remain
visible in the Repeater.

Let me know if this is not the case.

Well, for such scenario, I would recommend you use one of following two
approaches:

1) Bind the Repeater in every postback; this way the DropDownList will get
re-created in every postback.

2) Do not dynamically create the DropDownList, instead, create them in
Repeater's ItemTemplate; but we set their visibility based on the flag.


Let me know what do you think of these approaches.

Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
J

J055

Hi Walter

I don't think I understand what is the best approach at the moment. I don't
really want to add the second DropDownList control to each Repeater row
everytime the page is posted back. Most of the time the controls will be
visible=false. When the first DropDownList is post back to add the second
one then I'd like the second one to include an AutoPostBack event itself
which is already writen for other similar controls which are visible on each
page load.

The web page is very complex and will include many optional dynamic for the
user so it's important not to load every control each time when they will
only be used infrequently. Is there a recommended methodology for uses many
dynamic controls on a page?

Thanks
Andrew
 
W

Walter Wang [MSFT]

Hi Andrew,

Thanks for the update and Happy New Year!

If a control.Visible = false, normally it will not generate html output in
the response, therefore it will not impact on the web page performance if
user is running on a slow network connection.

HTTP protocol is stateless, a WebForm's control hierarchy needs to be
re-created at server-side in every postback. Even if you're not rebinding
the Repeater in each postback, the controls still get re-created at
server-side using the ViewState stored in the webform.

The recommended way to handle dynamic controls in ASP.NET is to re-create
them in appropriate places before ASP.NET engine restores state of them.
See

#ASP.NET Page Life Cycle Overview
http://msdn2.microsoft.com/en-us/library/ms178472.aspx

for more information.

If you're having many dynamic controls on your web form, I would recommend
you to create custom server control or user control to encapsulate some
functions. For example, you might want to create a composite control which
initially only contains one DropDownList, a second DropDownList is created
dynamically upon request. Then you could use this custom control in your
web page, this way your web page could be simplified a lot. Let me know if
you need further information regarding how to create a custom composite
control.

Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
J

J055

Hi Walter

I've created a custom server control as you suggested to separate some of
the code. I'm still having problems with the order of events being raised:

my new control is added to each item in a repeater which is in the main
page. When a dropdownlist (belonging to the server control) raises a
SelectedIndexChanged event the value needs to be available to the repeater
ItemCreated event but this fires before the SelectedIndexChanged event. I
place the value to a public property in the server control. The Repeater is
not DataBound so I can access the value in the ItemDataBound event either.

What approach would you suggest please?

Thanks
Andrew
 
W

Walter Wang [MSFT]

Hi Andrew,

Since I'm not quite clear about your actual requirement, I can only give
some general suggestion in my previous reply. For your updated question, I
think I may need more detailed explanation of your requirement (or even
some working code) so that I can suggest more. Thanks.

Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
J

J055

Hi Walter

I think the code is to much to paste in here. Can I send you the project
files? It will be easier to explain then I think.

Thanks
Andrew
 
W

Walter Wang [MSFT]

Sure. Send it to me via email.

Thanks.

Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top