Using Custom Control in a FormView

J

J055

Hi

I have a rather odd problem when using my custom control in a FormView
control. The custom control inherits the CompositeControl. It is two
DropDownLists. The first DDL binds to a DataSource internally. When a user
selects a value in the first DDL a second DDL is bound to another
DataSource, again internally, based on the selected value of the first DDL.

This all works well until I place the control in a FormView control. On
first page request the custom control is loaded with the first DDL populated
with data but the list contains the values twice, i.e.

Value1
Value2
Value3
Value1
Value2
Value3

This does not happen when the control is used without the FormView. I have
tried debugging by adding a break point to where the first DDL is data bound
and the method only appears to be called once and contains the correct
values. Can someone suggest what might be happening and how I can fix it? It
would be a real pain if I couldn't use the FormView.

Many thanks
Andrew
 
S

Steven Cheng[MSFT]

Hello Andrew,

From your description, you have developed a custom webserver control which
contains two dropdownlists (with cascaded data items). This dropdownlist
works well when it be put on page individually, however, you found the
dropdownlist contains duplidated items if it is put in a FormView control,
correct?
Based on my experience, such problem generally related to the custom
control's sub control population logic. Your own custom control will do the
control creation and data population such as databinding. And when you add
it into FormView, the creation and databinding will also related to the
FormView container. If convenient, would you provide the code logic of
your custom control or if possible you can try creating a simplified one
(or use a ascx usercontrol to simulate it) whic can repro the same
behavior. Thus, I can help you perform some local tests.

Please feel free to let me know if there is anything I missed.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead



==================================================

Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.



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 Steven

Here's some cut down code for my control. I think I need to know what logic
to add so that the control can be used both within a FormView or other
DataBound parent control and on it's own. Are there any 'best practices' I
should be aware of? Thanks Andrew

public class GroupsSetsDropDown : CompositeControl
{
private DropDownList ddlGroups = new DropDownList();
private DropDownList ddlSets = new DropDownList();

protected override void CreateChildControls()
{
Controls.Clear();
// only get data if visible is true
if (this.Visible == true)
CreateControlHierarchy();
ClearChildViewState();
}
protected virtual void CreateControlHierarchy()
{
CreateGroupsSetsDdl();
this.Controls.Add(ddlGroups);
this.Controls.Add(ddlSets);
}
private void CreateGroupsSetsDdl()
{
ddlGroups.Items.Add(new ListItem("Select...", "-1", true));
ddlGroups.AutoPostBack = true;
if (this.DesignMode == false)
{
Dictionary<int, string> groups = new GroupsBLL().GetLookup();
if (groups != null)
{
ddlGroups.AppendDataBoundItems = true;
ddlGroups.DataSource = groups;
ddlGroups.DataValueField = "key";
ddlGroups.DataTextField = "value";
//ddlGroups.SelectedIndexChanged += new
EventHandler(this.ddlGroupSets_SelectedIndexChanged);

// what conditions should be considered before adding this line?, i.e. if
the control is placed inside a FormView then the will do the binding.
ddlGroups.DataBind();
}
}
ddlSets.Enabled = false;
ddlSets.Items.Add(new ListItem("Any", "-1", true));
}
}
}
 
J

J055

Hi

Another thing I notice is that I get quite strange results when
EnableViewState = true. I guess I need to allow for this somehow in the
custom control?

Thanks again
Andrew
 
S

Steven Cheng[MSFT]

Thanks for your reply Andrew,

After some further troubleshooting on the code you provided, I found the
root cause of this issue. The double-data-population is caused by the
dropdownlist in your custom webcontrol have been called twice. Here is how
the ASP.NET page call the databind twice on them:

1. First time, it is in your custom webcontrol's control creation time, the
"CreateChildControls" method will perform databinding to populate the main
dropdownlist.

2. When you put the custom webcontrol in a template databound control(such
as FormView, repeater, datalist, gridView....), since the template
databound container will call DataBind(), this Databind method will
recursively call DataBind() method on all the child controls. And for your
scenario, the two DropDownLists in your custom webcontrols' Databind will
be called.

Currently, I've considerred the following two means to resolve the issue:

1) In the custom control's CreateChildControls code logic, instead of
databind, we manually copy each items from the Datasource into the
dropdownlist. e.g.

foreach(item in Dictionary)
{
ddl.items.Add(item.key, item.value)
}


2) Override your custom webcontrol's DataBind method and do not recursively
call sub control's databind method(remove base.DataBind). e.g.

public override void DataBind()
{
//remove the base.DataBind(); call
//base.DataBind();
}



Here is a complete code fragment of the modified control

================

[ToolboxData("<{0}:GroupsSetsDropDown
runat=server></{0}:GroupsSetsDropDown>")]
public class GroupsSetsDropDown : CompositeControl
{
private DropDownList ddlGroups;
private DropDownList ddlSets;

protected override void CreateChildControls()
{
Page.Response.Write("<br/>CreateChildControls+" + this.ID);

Controls.Clear();
// only get data if visible is true
//if (this.Visible == true)
CreateControlHierarchy();
//ClearChildViewState();
}


protected virtual void CreateControlHierarchy()
{
CreateGroupsSetsDdl();

}
private void CreateGroupsSetsDdl()
{
ddlGroups = new DropDownList();
ddlSets = new DropDownList();
ddlGroups.ID = "ddlGroups";
ddlSets.ID = "ddlSets";

this.Controls.Add(ddlGroups);
this.Controls.Add(ddlSets);




ddlGroups.Items.Add(new ListItem("Select...", "-1", true));
ddlGroups.AutoPostBack = true;



if (this.DesignMode == false)
{
Dictionary<int, string> groups = new
GroupsBLL().GetLookup();
if (groups != null)
{
ddlGroups.AppendDataBoundItems = true;
ddlGroups.DataSource = groups;
ddlGroups.DataValueField = "key";
ddlGroups.DataTextField = "value";

//ddlGroups.SelectedIndexChanged += new
EventHandler(this.ddlGroupSets_SelectedIndexChanged);

// what conditions should be considered before adding
this line?, i.e. if
//the control is placed inside a FormView then the will
do the binding.

ddlGroups.DataBind();
}
}


ddlSets.Enabled = false;
ddlSets.Items.Add(new ListItem("Any", "-1", true));
}

public override void DataBind()
{
//base.DataBind();
}
}
=================================

for custom webserver control development, you can refer to those reference
in MSDN:


#Developing Custom ASP.NET Server Controls
http://msdn2.microsoft.com/ru-ru/library/zt27tfhy.aspx

Also, I would like to lookup the ASP.NET built-in control code(through
reflector) to get some ideas when developing a custom webcontrol.

Hope this helps you.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


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

J055

Hi Steven

This is very useful stuff. I've used the first option of manually adding the
dictionary to the Dropdown and this works fine.

I have a another issue to do with the control which I would appreciate some
advice on.

I want to make sure that the control doesn't call the database (to populate
the list) if the control is visible = false. I think the last value is being
called from viewstate so I may be calling the database in the wrong part of
the page life cycle?
if (this.Visible == true)

{

//code to call db and add dictionary to DDL

}

I'd also like to use viewstate to store the ddl values from the database. I
know that the normal way to build databound controls is to have a separate
data source but it makes sense for me to do everything in the control as the
datasource is a permanent feature of this control.

Can you give me your thoughts on this?

Thanks again
Andrew
 
W

Walter Wang [MSFT]

Hi Andrew,

It's my understanding that the CreateChildControls() will not get called if
the control is not visible. Therefore I don't think you need to check for
visibility before binding data.

If you've bound the data to the DDL from database and the DDL has viewstate
enabled, I think you don't have to persistent the data yourself. I hope I
didn't misunderstand your question.

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,982
Messages
2,570,190
Members
46,740
Latest member
AdolphBig6

Latest Threads

Top