Last time we spent a lot of time on the SelectionController.  To conclude the series, we will hook the selection behavior into our CustomGridView.


Implementing the IRowSelectionView
There are quite a few events on the view that the CustomGridView needs to implement.  In addition to the event are a couple of behavior properties.

The properties are pretty simple.  I want them to be published, so I have identified them to be placed in the "Behavior" category:

    1 [Category( "Behavior" )]

    2 [DefaultValue( typeof( ListSelectionMode ), "Single" )]

    3 public ListSelectionMode SelectionMode

    4 {

    5     get { return (ListSelectionMode)( ViewState["SelectionMode"] ?? ListSelectionMode.Single ); }

    6     set { ViewState["SelectionMode"] = value; }

    7 }


    9 [Category( "Behavior" )]

   10 [DefaultValue( false )]

   11 public bool SelectOnRowClick

   12 {

   13     get { return (bool)( ViewState["SelectOnRowClick"] ?? false ); }

   14     set { ViewState["SelectOnRowClick"] = value; }

   15 }

Because the CustomGridView is a subclass of GridView, we can take advantage of the events that are already there.  Here is a list of events that we are using and we get for free:

    1 event GridViewPageEventHandler PageIndexChanging;

    2 event GridViewSortEventHandler Sorting;

    3 event GridViewRowEventHandler RowCreated;

    4 event GridViewCommandEventHandler RowCommand;

Then again, there are some events that we had to add in order to tap into some other GridView behavior.  If we had kept all of the selection behavior in the CustomGridView, we could have simply overridden a few methods.  But to keep separation, we chose to put the selection logic in a separate controller class.  One side effect is that we are forced to add a few extra events to meet our needs.  For example:

    1 event EventHandler _rowSelection_ChildControlsCreated;

    2 event EventHandler IRowSelectionView.ChildControlsCreated

    3 {

    4     add { _rowSelection_ChildControlsCreated += value; }

    5     remove { _rowSelection_ChildControlsCreated -= value; }

    6 }


    8 event EventHandler _rowSelection_PageSizeChanging;

    9 event EventHandler IRowSelectionView.PageSizeChanging

   10 {

   11     add { _rowSelection_PageSizeChanging += value; }

   12     remove { _rowSelection_PageSizeChanging -= value; }

   13 }


   15 event EventHandler _rowSelection_DataSourceViewChanged;

   16 event EventHandler IRowSelectionView.DataSourceViewChanged

   17 {

   18     add { _rowSelection_DataSourceViewChanged += value; }

   19     remove { _rowSelection_DataSourceViewChanged -= value; }

   20 }

You'll probably notice that I implemented these events explicitly.  I could have used implicit implementations for the most part, but there were at least a couple of event names that conflicted with other controllers that I am hooking into my custom GridView.

Of course we need to fire these events as well.  For each of the events listed above, I have overridden base GridView methods (one property) in order to provide the event hooks:

    1 protected override void CreateChildControls()

    2 {

    3     base.CreateChildControls();


    5     if(_rowSelection_ChildControlsCreated != null)

    6         _rowSelection_ChildControlsCreated( this, EventArgs.Empty );

    7 }


    9 public override int PageSize

   10 {

   11     get

   12     {

   13         return base.PageSize;

   14     }

   15     set

   16     {

   17         if(base.PageSize != value)

   18         {

   19             if(_rowSelection_PageSizeChanging != null)

   20                 _rowSelection_PageSizeChanging( this, EventArgs.Empty );


   22             base.PageSize = value;

   23         }

   24     }

   25 }


   27 protected override void OnDataSourceViewChanged( object sender, EventArgs e )

   28 {

   29     if(_rowSelection_DataSourceViewChanged != null)

   30         _rowSelection_DataSourceViewChanged( sender, e );


   32     base.OnDataSourceViewChanged( sender, e );

   33 }

Initializing the SelectionController
The final piece is for the CustomGridView to call on the services of SelectionController.  I've added that logic to the OnInit method of the GridView.

    1 protected override void OnInit( EventArgs e )

    2 {

    3     ...


    5     if(RowSelectionEnabled)

    6     {

    7         _selectionController = SelectionController.GetInstance();

    8         _selectionController.Observe( this );

    9     }


   11     ...

   12 }

That's pretty much all there is to it.  We put most of the heavy lifting in the SelectionController so the CustomGridView is pretty simple.

It is clear that there is nothing real advanced here.  I am sure a lot can be done to clean things up a bit.  For example, I could use an IoC container to hook my controller into my GridView.  Also, there are a lot of really good professional GridViews out there.  I took this approach because I needed two custom behaviors, one of which was not supported by any of the products I was looking into.  I also work for a start-up company that has been watching our budget pretty closely.  So a day or two working on the customizations was worth it.

Since writing these customizations, though, we have decided to buy a suite of UI components, including a GridView.  The new component meets part of our need and comes really close on the other.  We are hoping to tweak the new grid view to meet our needs in the near future.

Concluding Thoughts
This series was intended to help those of you teetering on the edge of control customization.  It clearly was not a step by step walkthrough.  However, I hope that it has provided some guidelines that might influence your thought process when you are ready to jump in and make your own customizations.

posted on Friday, November 14, 2008 8:07 PM
Filed Under [ .Net Design ASP.Net C# Design Principles ]


No comments posted yet.

Post A Comment