Implementing two-way Data Binding for ASP.NET

Wrapping Up

A few more odds and ends

While in the process of subclassing and dealing with data binding it's also useful to address some things that just don't quite seem to work right in ASP.NET. For example, listboxes do not persist their SelectedValue unless you use ViewState, which is very annoying if you don't want to ship the content of your lists over the wire each time.  This is actually quite easy to fix with

override protected void OnLoad(EventArgs e)
{
  base.OnLoad(e);

  /// *** Handle auto-assigning of SelectedValue
  /// *** so we don't need Viewstate to make this happen
  if (!this.EnableViewState && this.Page.IsPostBack)
  {
        string lcValue = this.Page.Request.Form[this.ID];
        if (lcValue != null)
              this.SelectedValue = lcValue;
  }
}

Voila, you no longer need Viewstate to postback the selected value.

Another problem I ran into on several admin forms is that Passwords in text boxes are not posted back to forms. This is possibly not a bad idea, but a problem when you really need to post a password back for admin purposes and you don't want to have people keep retyping the password each time.

override protected void OnLoad(EventArgs e)
{
  base.OnLoad(e);

  // *** Post back password values as well - you can always clear manually
  if (this.TextMode ==  TextBoxMode.Password)
        this.Attributes.Add("value", this.Text);
}

A few limitations

Ok, all of this stuff probably sounds pretty good to you right about now. But be aware that there are a few limitations to what I've shown you so far.

  • Binding doesn't work against indexed objects or properties
    You can't bind against collections or arrays or any member that resolves through collections or arrays. For example, you can bind to a DataRow if you have a simple property that points at this DataRow (such as the Customer.DataRow in my examples), but you cannot bind to it with Customer.DataSet.Tables["wws_Item"].Rows[0]. All resolving will fail if an enumerated type is encountered. This can be fixed with some changes to the Reflection wrappers, but I haven't time to look into this. Although this seems like a big deal you can always work around this by using wrapper properties either on your form or your objects. If you look at the sample code I expose an InvTable property on the form to bind against the Table for example. The code simply sets this property when the table is loaded.
  • Binding to Private members is not possible
    Because all binding occurs inside of an external class Private members are not accessible to Reflection. This means any objects you bind to must be protected or public.
  • Subclassed controls don't work well with child templates
    If you subclass controls like the ListBox or DropDownList and manually assign values in the HTML template, you'll find that because of the type prefix for the control standard template expressions don't show Intellisense. So although you can continue to use <asp:ListItem> from within <ww:wwWebDropDownList> you will not get Intellisense. On the other hand if you do a lot of stuff with templates manually you probably don't need data binding anyway – in that case just use the stock controls.

None of these are show stoppers, but they are things you should be aware of before you take off on this path.

Summing up

Although it's such a downer that ASP.NET doesn't include better data binding support natively, it also say a lot for the architecture that you can extend controls easily enough to provide this functionality with a relatively little amount of code. I suspect most serious developers end up subclassing the stock controls anyway and so adding this stuff in is only a small step anyway.

There's a lot more that can be done with the basic extensions I've built here. For example it'd be real nice to build better input formatting into this stuff, providing things like InputMasks that could be handled client side. ASP.NET provides Validation controls, but again the design is generally more work than it needs to be. A single validation property would be very cool. In any case there are many extensions that would be useful, but I hope you find this base useful and something you can extend. If you end up enhancing this stuff please send me a line so I can check it out.

Next time around I'll take a look at Windows Forms and how we can build simple data binding controls in much the same way as we did here to simplify behind in rich client applications.

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Better train people and risk they leave – than do nothing and risk they stay.” - Anonymous