DataBind and Multiviews

If you are using a multiview in asp to display a bunch of different pieces of information, for example if you are displaying a bunch of logs that are selectable inside your multiview (using the tabbed control I posted here recently), you need to be careful about how you display the data.  The way that GridView's work is if you set a DataSourceID on them they bind automatically when the page is loaded.  This is probably not the behavior you want, since that means all of you views will bind and load when the page is loaded which can slow things down a lot if you have a bunch of views in your multiview.  The way to get around this is to only call DataBind() on the sepcific view that is current being displayed.  This requires you to change the DataBind() call ont he multiview so it doesn't call base.DataBind() (since this will call DataBindChildren()).  Make the DataBind() on the Multiview only call the DataBind of the currently selected view.  In the DataBind code for your user control or whatever you have inside the view, you then set the datasourceid on the gridview.  This means you still get all the bonuses of using a DataSouceID without it loading all the data in all the views of your multivirew when first loading it.

I put a bunch of traps on the DataBInd and DataBIndChildren on the various calls and found that it is not easy to intercept the automatic databinding done by the GridView when it first loads.  It is not really easily possible to make a delayed data bind grid view (although this is another possibility).  You could do this by intercepting the call to the DataSourceID call and keeping track of it yourself and only setting it on the base when a DataBind() is called.  With some experimentation I found that this proved to have more problems than just overriding DataBind() on the various user controls. Since doing the override also made me think about other things that might need to be delay bound.

The following code is a snippet for the MultiView showing how to override it to only DataBind the specifically active view. The DataBind() call ends up heirachically going down the control tree, so anything lower than it will have DataBind() called on it when the DataBind is called on the view itself.

    /// <summary>
    /// This multiview will only databind the active view, not any other views.
    /// </summary>
    [ToolboxData("<{0}:MultiViewActiveDataBind runat=server></{0}:MultiViewActiveDataBind>")]
    public class MultiViewActiveDataBind : MultiView
    {
        protected override void DataBindChildren()
        {
            // Only data bind the currently active view.
            if (this.ActiveViewIndex != -1)
            {
                this.Views[this.ActiveViewIndex].DataBind();
            }
        }
    }