Tags: , , , | Categories: Articles Posted by RTomlinson on 1/7/2010 7:07 AM | Comments (6)

Today I spent a stupid amount of time trying to resolve an issue that had me banging my head off the desk. To save anyone else from the sheer frustration I thought I would write about it to hopefully save anyone else from wasting their time.

I began writing a custom composite control that contained a dropdownlist. This dropdownlist required data binding to a list of business objects. Simple and common scenario. I would then databind the dropdownlist to the control in the page behind (see code sample below).

   1:  using System;
   2:  using System.Web;
   3:  using System.Web.UI.WebControls;
   4:  using System.ComponentModel;
   5:   
   6:  namespace SSControls
   7:  {
   8:      public class MapControl : CompositeControl
   9:      {
  10:          public MapControl() { }
  11:   
  12:          DropDownList _ddlAccountTypes = new DropDownList();
  13:   
  14:          public DropDownList AccountTypes
  15:          {
  16:             get
  17:             {
  18:                 return _ddlAccountTypes;
  19:             }
  20:          }
  21:   
  22:          protected override void CreateChildControls()
  23:          {
  24:              Controls.Add(_ddlAccountTypes);
  25:          }
  26:      }
  27:  }

   1:  public class AccountMap : System.Web.UI.Page
   2:  {
   3:      protected void Page_Load(object sender, EventArgs e)
   4:      {
   5:        if (!IsPostBack)
   6:        {
   7:            mapControl.AccountTypes.DataSource = Accounts.GetAccounts(123);
   8:            mapControl.AccountTypes.DataBind();
   9:        }
  10:      }
  11:  }

As simple as it sounds whenever a postback was issued the data in the dropdownlist was lost. Now the first thought of any developer is probably that this is either a ViewState issue or a databinding issue.

Let's think about what happens when we perform data binding on a composite control. The benefit of inheriting from CompositeControl is that child controls have their ViewState automatically tracked and we don't have to go through the pain of the whole IPostBackEventHandler complexity and the loading and saving of ViewState.

So why do we lose our data upon postback? The problem is that ViewState is only tracked once it has been added to the Controls collection in the CreateChildControls() method. Therefore if we call DataBind() on a child control before it is added to the Controls collection then the ViewState is not being tracked. The result of this (apart from a massive headache) is that when we issue a postback we lose the ViewState information from out dropdownlist. 

The solution? As painful as it is for me to say, make sure that you data bind after your child control has been added to the controls collection, as follows:

   1:  using System;
   2:  using System.Web;
   3:  using System.Web.UI.WebControls;
   4:  using System.ComponentModel;
   5:   
   6:  namespace SSControls
   7:  {
   8:      public class MapControl : CompositeControl
   9:      {
  10:          public MapControl() { }
  11:   
  12:          DropDownList _ddlAccountTypes = new DropDownList();
  13:   
  14:          public DropDownList AccountTypes
  15:          {
  16:             get
  17:             {
  18:                 return _ddlAccountTypes;
  19:             }
  20:          }
  21:   
  22:          protected override void CreateChildControls()
  23:          {
  24:              Controls.Add(_ddlAccountTypes);
  25:              if (!Page.IsPostBack)
  26:                  _ddlAccountTypes.DataBind();
  27:          }
  28:      }
  29:  }

   1:  public class AccountMap : System.Web.UI.Page
   2:  {
   3:      protected void Page_Load(object sender, EventArgs e)
   4:      {
   5:        if (!IsPostBack)
   6:        {
   7:            mapControl.AccountTypes.DataSource = Accounts.GetAccounts(123);
   8:        }
   9:      }
  10:  }

Now when a postback is issued your dropdownlist will have it's values tracked in ViewState and you will not lose data.

Share or Bookmark this post…
  • del.icio.us
  • Digg
  • DotNetKicks
  • Facebook
  • Slashdot
  • StumbleUpon
  • Reddit
  • Technorati
  • TwitThis

Comments

pingback
topsy.com on 1/7/2010 6:20 PM Pingback from topsy.com

Twitter Trackbacks for
        
        Ryan Tomlinson | Databinding child controls in an ASP.NET composite control.
        [ryantomlinson.com]
        on Topsy.com
trackback
DotNetKicks.com on 1/14/2010 11:45 PM Databinding child controls in an ASP.NET composite control.

You've been kicked (a good thing) - Trackback from DotNetKicks.com
TABATHA
TABATHA Latvia on 4/17/2010 8:15 PM Interesting post Smile What a super blog!
Albert
Albert United States on 4/27/2010 5:43 PM I'd recommend turning on tracing in your page (Trace="True") since it'll show you how the controls are nested and hopefully give you ideas on how to approach accessing the controls.  You should be able to use the syntax shown above although some of the container control IDs may not be known which would make it a bit difficult.
Nicholas
Nicholas United States on 6/3/2010 8:53 PM I faced this postback problem for a week ago and many thanks to you for helping me to resolve it.
Flowers
Flowers United States on 8/17/2010 5:16 PM I'd recommend turning on tracing in your page.  since it'll show you how the controls are nested and hopefully give you ideas on how to approach accessing the controls.

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading