posted on Wednesday, February 02, 2005 8:48 AM by mlorengo

Further Refinement with the ObjectDataSource Control

In order to take advantage of the new GridView control in Asp.Net 2.0, I've been researching how too use the new ObjectDataSource control, and add support for it in my Virtual Cellar application. I now have two classes in the Virtual Cellar Model that will serve as the candidate classes for use as an ObjectDataSource. A lot of Asp.Net 2.0 examples use the SqlDataSource control to illustrate the GridView features, this entry will list some resources that specifically apply to using the ObjectDataSource

As I mentioned in my last post, I was trying to determine how to prevent the GridView from being populated on the first page load. I found the following note in the ObjectDataSource documentation.

The ObjectDataSource control retrieves data whenever the Select method is called. The Select method is automatically called by controls bound to the ObjectDataSource when their DataBind method is called. If you set the DataSourceID property of a data-bound control, the control automatically binds data when a Web page loads. However, if you set the DataSource property, you must explicitly call the DataBind method of the data-bound control. You can call the Select method programmatically at any time to retrieve data.

So, it turns out that specifying the DataSourceId property autobinds the control. This is more of that "no-code" model in Asp.Net 2.0. In order to suppress the autobind, I simply removed the DataSourceId attribute from my .aspx page. This prevents the GridView from being populated on the page load. It also removes the link between the GridView and the ObjectDataSource, so I now have to setup a TextChanged handler do to the binding.

protected void ProducerSearchTextbox_TextChanged(object sender, EventArgs e)
{
	producerGridView.DataSource = producerDataSource1;
	producerGridView.DataBind();
}

The above snippet sets the DataSource property to my ObjectDataSource control's Id property. This is equivalent to setting the DataSourceId = "producerDataSource1" property in the .aspx page, except that it doesn't autobind on page load. Then I call the DataBind() method.

I refactored a lot of the Repository code right out of my model. My reason for doing this was to satisfy a requirement that the ObjectDataSource have a parameterless default constructor. It turns out that you can overcome this requirement by handling the ObjectCreating event on the ObjectDataSource and performing my own construction. As it turns out, the new code model seems to fit better, and I eliminated a lot of classes that I just don't need yet if ever. My new class diagram looks like this.

Bigger picture here

 

The WineDataSource and ProducerDataSource replace the WineRepository and ProducerRepository classes. The Builder classes are responsible for creating actual instances of the Wine and Producer classes, thereby segregating the responsibilities of each class. In order to make the *DataSource classes more friendly to the DataSource configuration wizard, I've decorated them with the following attributes.

[DataObject]
public class WineDataSource
{

  public WineDataSource()
  {
  }

  [DataObjectMethod(DataObjectMethodType.Select, true)]
  public IList<Wine> SelectByProducerId(int id)
  {
    return GetWineList(this.wineProvider.GetByProducerAsDataReader(id));
  }

  [DataObjectMethod(DataObjectMethodType.Select)]
  public IList<Wine> SelectById( int id )
  {
    return GetWineList(this.wineProvider.GetAsDataReader(id));
  }

  //...
}

The DataObject attribute on the class level tells the wizard that this is a DataSource class. The DataObjectMethod attribute exposes the SelectByProducerId(int id) as a DataObjectMethod, and more specifically a "Select" method. The second boolean argument specifies that this is the default "Select" method. Here's how it looks in the designer.

The only items that will display in the drop down list are those that have been marked with the [DataObject] attribute (as long as the Show only data components checkbox is selected). This eases the clutter when your project consists of a lot of classes.

The next step is to choose the Select method. Again, only those methods with a DataObjectMethod and a DataObjectMethodType of Select will be shown.

In conclusion, I've illustrated how to prevent the autobinding from occurring on the page, refined my class diagram to reflect the addition of the new xxxxDataSource classes, and demonstrated the use of the DataObject attributes (which are in System.ComponentModel).

Comments