# Friday, July 4, 2008

July 3 (Contribupendence Day) is almost over.  As promised, I wrote reviews for several colleagues on LinkedIn.  Most of the people I reviewed were those I worked with directly at my last employer.  I am currently on a project that allows me to work directly with a couple folks from my current employer

I became motivated enough that I ended up writing 7 reviews tonight (I had only promised 5) and I invited quite a few new people to connect with me on LinkedIn and Plaxo

I was surprised at the number of past and present colleagues that are using these networking sites.  My connections should at least double in the next few days.

Hopefully the people I recommended will be inspired to pick 5 people of their own and this thing will explode.

My plan is to write more recommendations in the coming weeks.  I have some that I've written but cannot make official until the recipient accepts my connection invitation. 

I won't copy my recommendations on this site but you are welcome to read them here.

Again thanks to Jeff for suggesting this.

Friday, July 4, 2008 3:08:05 AM (GMT Daylight Time, UTC+01:00)
# Thursday, July 3, 2008

Tomorrow - July 3 - is Contribupendence Day.

What is Contribupendence Day, you ask?  Well it's the day when all readers of my blog agree to send me $20.

Not really.  Contribupendence Day is the brainchild of Microsoft Developer Evangelist Jeff Blankenburg, who woke up one day and noticed the untapped potential of networking sites such as LinkedIn, Plaxo and Facebook.  These sites give us the opportunity to recommend or comment on those we have worked.  Unfortunately, few of us take advantage of this feature which is a shame.  These recommendations could be a good source of feedback to potential employers and might make the difference in getting an interview or landing a job.

He's right of course. I've been on LinkedIn for a couple months and I am connected to a few dozen people but these are very passive connections.  In the back of my mind, I tell myself I'll focus on LinkedIn the next time I look for a job (which hopefully won't be for a long time).  The problem with this attitude is that I'm relying on everyone else to motivate themselves around my schedule.  When I'm ready to look for a job, will others have the time to write a glowing review for me?  If I worked for or with them, will they even remember my specific accomplishments?

So, at Jeff's urging, I'm being proactive.  Tomorrow I resolve to write reviews of 5 people on LinkedIn.  In doing so, I hope to inspire these 5 to either review me or to review someone else, which will set in motion a process that may very well come back to me.

I've worked with some great people in my life so it wasn't difficult to pick five that I can rave about.  I'll be reviewing them tomorrow and I urge you to do the same.

Happy Contribupendence Day everybody!  And you are welcome to review me.  Or, if that's too much trouble, just send me the 20 bucks.

Thursday, July 3, 2008 3:24:25 AM (GMT Daylight Time, UTC+01:00)
# Tuesday, July 1, 2008

The ann arbor Give Camp is July 11-13 at Washtenaw Community College - less than two weeks away.  For those who haven't heard, this is a great opportunity to contribute to some worthy causes, flex your tech muscles and network with the developer community. 

At this event, software developers, DBA, project managers and UI designers will get together and develop projects for local charities.  So many charities requested projects for this camp that most had to be turned away due to lack of resources.  The more people involved, the more charities we can help.  The facilities will be available and staffed round-the-clock on this weekend and refreshments will be provided.  For security reasons, you must register in advance in order to participate.  Jennifer Marsman of Microsoft is organizing the camp. 

I will be out of town with my son the weekend of the event, but I volunteered to help with some of the evaluations of the projects because it I really wanted to contribute.

You can get more information and you can register for this great outing at http://www.annarborgivecamp.org/.  If you will be in town, please take a look and consider giving your time.

Tuesday, July 1, 2008 4:49:47 PM (GMT Daylight Time, UTC+01:00)
# Thursday, June 26, 2008

Binding to a GridView

ASP.Net data binding is a great technology for developers who want to create interactive web applications without writing a lot of code. For example, a developer can drop a GridView and a DataObject onto a web form, set a few properties and have a fully editable grid, allowing users to easily view and update data. 

Even sorting the grid data can be performed without writing any code.  Just set the GridView's AllowSorting property to "true" and set the SortExpression property of any "sortable" column. 

<asp:GridView
   ID="GridView1"
   runat="server"
   AllowSorting="true"

...

   <asp:BoundField
      DataField="Name"
      HeaderText="Product Name"
      SortExpression="Name" />

...

By default, the grid renders a link at the top of each sortable column.  Clicking this link toggles the sort order between 3 states: Ascending, Descending and No Sort. 


Sorting Limitations

But there is a "Gotcha".  The GridView can be bound to any set of data - that is, to any object that implements the System.Collections.IEnumerable interface.  This includes a DataTable, ArrayList, List and HashTable, among others.  However the automatic sorting only works when binding to a DataTable.

Personally, I prefer to work with and bind to generic Lists.  A List is more flexible than a DataTable and does a better job of abstracting the user interface from the back-end data source, making it easier to swap out one or the other.

But by binding to a List, I sacrifice the automatic sorting that happens when I bind to a DataTable.  Fortunately, it doesn't take a lot of code to implement sorting on a GridView bound to a generic List.

How to sort a GridView bound to a List

First, we set the GridView AllowSorting property and each column's SortExpression property as described above.  This provides "sort" links at the top of each column.  Unfortunately these links will not work properly - in fact, clicking them will generate an error.

To get this to work, you must do the following

  1. Add an extra "sortby" parameter of type string to your Select method.
  2. Add code to your sort method to sort the list before returning it (more on this later)
  3. Add a SortParameterName attribute to your ObjectDataSource.  The value of this parameter should be the same as the parameter you added to your Select method.

By setting the SortParameterName attribute, we are telling ASP.Net to pass sorting information to the Select method and which parameter to pass it to.  The Select method gets called when the grid loads or refreshes and whenever the user clicks the "sort" links at the top of each column.  Most of the time, the value passed to the sortby parameter is an empty string (indicating no sort order), but if the user clicks a "sort" link, this parameter will contain one of the following three values

  • "<SortField> ASC"
  • "<SortField> DESC"
  • ""

where <SortField> is the string specified in the SortExpression attribute of the column clicked.  With each click, the grid column cycles its sort between ascending order, descending order, and no sort.  The parameter value passed depends on which is currently the active sort. 


<asp:ObjectDataSource ID="ProductObjectDataSource" runat="server" 
      SelectMethod="GetProductsList"
      TypeName="DemoGridBusLayer.NWindBL"
      SortParameterName="sortBy">
</asp:ObjectDataSource>

Now, how do we sort a List?  More specifically, how do we sort a list when we don't know in advance on which column we are sorting or in which direction (ascending or descending)? 

A List has a Sort method, so we can call that.  But what does it mean to sort a list of objects?  An object has properties and we can sort on any one (or more) of those properties, as long as the property is of a type that can be sorted.  We need to specify on which object property we will be sorting.  To do this, we use an overload of the List.Sort method that accepts an IComparer object.  IComparer has a Compare method that tells the Sort method how to order each pair of objects in the list.  We can create a class that implements IComparer, override the Compare method and use reflection to determine at runtime on which property to sort.  The name of the property and the sort order (Ascending or Descending) can be passed into the class constructor. 

The code for this class (named GenericComparer) below:

using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Reflection;

namespace DemoGridBusLayer
{
    /// <summary>
    /// This class is used to compare any
    /// type(property) of a class for sorting.
    /// This class automatically fetches the
    /// type of the property and compares.
    /// </summary>
    public sealed class GenericComparer<T> : IComparer<T>
    {
        public enum SortOrder { Ascending, Descending };

        #region Constructors
        public GenericComparer(string sortColumn, SortOrder sortingOrder)
        {
            this._sortColumn = sortColumn;
            this._sortingOrder = sortingOrder;
        }

        /// <summary>
        /// Constructor when passing in a sort expression containing both the Sort Column and the Sort Order
        /// e.g., "BPCode ASC".
        /// </summary>
        /// <param name="sortExpression"></param>
        /// <remarks>
        /// This constructor is useful when using this with the ASP.NET ObjectDataSource,
        /// which passes the SortParameterName in this format
        /// </remarks>
        public GenericComparer(string sortExpression)
        {
            string[] sortExprArray = sortExpression.Split(" ".ToCharArray());
            string sortColumn = sortExprArray[0];
            SortOrder sortingOrder;
            sortingOrder = SortOrder.Ascending;
            if (sortExprArray.Length > 1)
            {
                if (sortExprArray[1].ToUpper() == "DESC")
                {
                    sortingOrder = SortOrder.Descending;
                }
            }

            this._sortColumn = sortColumn;
            this._sortingOrder = sortingOrder;
        }

        #endregion



        #region public properties
        /// <summary>
        /// Column Name(public property of the class) to be sorted.
        /// </summary>
        private string _sortColumn;
        public string SortColumn
        {
            get { return _sortColumn; }
        }

        /// <summary>
        /// Sorting order (ASC OR DESC)
        /// </summary>
        private SortOrder _sortingOrder;
        public SortOrder SortingOrder
        {
            get { return _sortingOrder; }
        }

        #endregion

        /// <summary>
        /// Compare two objects of the same class,
        /// based on the value of a given property
        /// </summary>
        /// <param name="x">First Object</param>
        /// <param name="y">Second Object</param>
        /// <returns>int</returns>
        public int Compare(T x, T y)
        {

            // User reflection to get the property
            PropertyInfo propertyInfo = typeof(T).GetProperty(_sortColumn);

            // Cast the property to IComparable, so we can use the built-in compare.
            IComparable obj1 = (IComparable)propertyInfo.GetValue(x, null);
            IComparable obj2 = (IComparable)propertyInfo.GetValue(y, null);

            // Order depends on Asc vs Desc.
            if (_sortingOrder == SortOrder.Ascending)
            {
                return (obj1.CompareTo(obj2));
            }
            else
            {
                return (obj2.CompareTo(obj1));
            }
        }
    }
}


Within our select method, we can call the List's Sort method and pass in an instance of the GenericComparer class, specifying on which column and in which direction to sort the list.  The SelectMethod is shown below.  (The details of querying a database and storing results into a List of objects is omitted.)

        /// <summary>
        /// Get a sorted list of all products
        /// </summary>
        /// <param name="sortBy"></param>
        /// <returns></returns>
        public static List<Product> GetProductsList(string sortBy)
        {
            // Get a list of Business Processes
            List<Product> prodList = GetProductsList();

            // Sort list
            if (sortBy != "")
            {
                GenericComparer<Product> cmp = new GenericComparer<Product>(sortBy);
                prodList.Sort(cmp);
            }
            return prodList;

        }

    }
}

With a small amount of code, we can enable sorting of a List of objects bound to a GridView in the same way that sorting is enabled for a DataTable bound to a GridView.

Demo

You can download the entire sample described in this article here: DemoGridSort.zip (39.63 KB).  You will need the AdventureWorks sample SQL Server database for this demo.

Thursday, June 26, 2008 5:05:33 PM (GMT Daylight Time, UTC+01:00)
# Tuesday, June 24, 2008

Did you know that every time an Ajax control performs a partial postpack, every event in the life cycle of the control's containing page or pages fires?

To me, this seems counterintuitive - There is no refresh of the containing page or of the master page, yet the Page_Load of both events fire.

I ran into it when I witnessed some unexpected behavior in a colleague's Ajax control.  After some investigation I saw the behavior was caused by code in the Page_Load event handler.  I thought this was a bug until I learned it was by design.  So we ended up bracketing some of the Page_Load code, testing the value of Page.IsPostBack to prevent code from running when it should not.

Tuesday, June 24, 2008 3:51:57 PM (GMT Daylight Time, UTC+01:00)
# Sunday, June 22, 2008

I had a terrific time yesterday at the Lansing Day of .Net yesterday. 

This was the last in an ambitious string of community-sponsored events in Michigan and Ohio under the "Day of .Net" branding.  In the past two months, DODN events have been held in Wilmington, OH, Grand Rapids, MI, Cleveland, OH, and Lansing, MI.  I managed to make the two Michigan events but family commitments kept me from the ones in Ohio.

A Day of .Net event features numerous speakers (usually about 30) speaking on topics related to software development.  The primary focus is .Net development but peripheral topics are almost always included.  I heard a very good talk yesterday by Dan Rigsby on the agile methodology in which software was barely mentioned.

Prior to yesterday, I wondered if the Lansing event might be anticlimactic coming so soon after three similar events.  I worried for nothing.  In fact, the opposite was true.  They managed to attract an excellent group of speakers, a full slate of sponsors (meaning, among other things, many cool door prizes) one of the better facilities I've seen (Lansing Community College West Campus) and the mayor of Lansing.  People were generally excited about this event.  I've heard - but can't confirm - that the Day of .Net was covered by two TV stations.  Jeff McWhirter and his group did a great job putting this together.  I don't know who thought of inviting the mayor, but that was a good idea.

The best part of these events is interacting with the people in the community.  There was a lot of good discussions about various projects, the state of the industry, the role of the community and the various approaches to developing software. 

When it was over, many of us headed over to Jeff's house to celebrate into the night.  I left at around 11 and the place was still packed and the bonfire was blazing.  Mike Wood, an old friend from my Cincinnati days stayed at my house before heading home this morning.

I picked up some nice swag - a copy of Camtasia, a logo t-shirt, and a pint glass featuring the LDODN logo.  This morning, I noticed that the t-shirt includes the slogan "I was there" but the pint glass has a modified slogan "I think I was there".

Here are some photos of the day: Photos.

 

>Lansing Day of .Net, 21 June 2008 - I'll be there!
Sunday, June 22, 2008 5:13:40 PM (GMT Daylight Time, UTC+01:00)
# Tuesday, June 17, 2008

I've heard people suggest that developing web applications is easier than building Windows applications.  Common sense tells us that this is not true - The tools for Windows applications are far more powerful and give us access to the entire Windows API as well as APIs that access the Internet).  In addition, we typically don't need to deal with messy things like viewstate and session state when writing Windows apps.  Because Windows apps tend to be stateful, this stuff is far easier to design and code.

What most people mean when they say that Windows apps are easier is that user's expectations tend to be lower for web application.  Most users understand the limitations of building a web app and will not be as demanding when requesting features.

However the tools available are changing that.  With tools like Silverlight and Flash, we can now build web applications that have a look and feel similar to fat clients.  And the advances in databinding controls make it far easier to manage state in a web app than just a few years ago.

As a result, user expectations of web applications are increasing.  Why shouldn't they demand the same rich user experience they get from their desktop apps? 

Take a look at the Cooper Mini site (http://www.miniusa.com) where you can find a dealer or build a cooper with the options you want. 
This site was built using Flash.

Or view the memorabilia collection at HardRock.com (http://memorabilia.hardrock.com/) where the developers used Silverlight to provide a very cool way of viewing the collection.

The User interface of each of the above sites exceeds that of most Windows applications.

Each quarter, the line blurs more between web applications and desktop applications.  Soon users will no longer temper their expectations based on the platform on which you develop.

Will you be ready for these increased expectations?

Tuesday, June 17, 2008 2:26:34 PM (GMT Daylight Time, UTC+01:00)
# Sunday, June 15, 2008
 #
 

Today is Father's Day here in America.  I spent the day with my two sons.  We went to church, then to lunch, then back home, where my sons hung out with their friends and I stayed in the background, content in knowing that they are safe and happy.

I look back on the difficulties of my life the last few years - an unwelcome separation, move, and divorce - and I realize that the one good, stabilizing thing in my life is the love of my boys.  I don't know how I would have made it without them.  I try to give them as much as I can and I hope that someday they recognize that.  But I know that they have given to me something that I could never receive from any other source - a reason to keep going; a reason to believe; a reason to hope for a better future. 

I know my boys will never doubt the fact that I love them with all my heart; but I doubt they realize the positive impact they have just by being in my life.  I've tried to communicate this but words fall short.

Nick and Timmy, if you are reading this, I love you more each day.

And to all the fathers out there, I wish for you the ability to express to your children the love you feel.  May they never spend one second doubting that their father loves them.

Sunday, June 15, 2008 11:52:27 AM (GMT Daylight Time, UTC+01:00)
# Thursday, May 22, 2008

Last night at the Southeast Michigan .Net User Group (http://www.migang.org/), I saw a great presentation on Microsoft Silverlight.  Jason Beres of Infragistics was the presenter. 

In the past six months, I've probably seen half a dozen presentations on the topic.  What set this one apart from the others was the amount of code that was shown.  While other presentations featured on showing off the eye candy (such as streaming video and rotating objects) that Silverlight supports, Jason stepped through the code in each of his demos. 

It made the process of writing Silverlight applications seem less intimidating and now I am resolved to explore this technology shortly.

Thursday, May 22, 2008 5:43:18 PM (GMT Daylight Time, UTC+01:00)
# Sunday, May 11, 2008

WM Day of .Net May 10, 2008 - I'll be there!

Yesterday I drove to Grand Rapids for the West Michigan Day of .Net.

I enjoyed the event, despite suffering from heartburn most of the day,

Here is a brief summary of the best sessions I saw

How to Architect Rich Internet Applications

Microsoft architect Josh Holmes gave an overview of what makes up a good rich internet application and when you should attempt to build one.

Getting Started with the ASP.Net MVC Framework
Tim Wingfield of Quick Solutions discussed the MVC framework.  This one had a lot of code samples.

A trip around the block with Rhino.Mocks
This session (led by Quick's Steve Hartman) was more like a roundtable discussion than a presentation.   Steve went through some definitions; stepped through a code sample; then started a discussion with the attendees about different Mock frameworks.

Reliable Messaging in WCF
James Bender of Quick Solutions gave this demo which also contained some good code samples.

A similar event is scheduled next Saturday in Cleveland.   I doubt I'll make that one, but I plan to attend the recently-announced Lansing Day of .Net scheduled June 21.

Lansing Day of .Net, 21 June 2008 - I'll be there!
Sunday, May 11, 2008 8:42:02 AM (GMT Daylight Time, UTC+01:00)