Monday, January 31, 2011

Back to mobile!

I'm back to writing mobile code. After seeing renewed my MVP status, I was able to get my hands on a loaner developer Windows Phone 7 device. I have to personally thank Cristina Gonzales Herrero from Microsoft Spain for both  (MVP and the phone).

Having a WP7 phone on my hands was just the excuse I needed to get back to mobile development. The first hurdle I had to overcome was the App Hub registration. My first attempt was to use my own company account to enroll but the registration process requires two people from the company. So what happens to companies of one like mine? Well, I turned back and took the individual path only to be greeted by payment form (yes, you have to pay USD $99 to deploy to the phone), that assumed I was a US citizen. After talking to some friends, I understood that the only way to go about this was to create a live.com.pt (I live in Portugal) account, but, before I could do that, I had to change my language preferences on IE. You see, I just cannot use a development machine with a Portuguese OS. The keyboard is OK, but not the OS "translations". I started developing on computers that could hardly "speak Portuguese" so I got used to the English language for development, and this also includes the language preferences on the browser. Incidentally, if you don't have Portuguese as your first browser language selection, you cannot create a live.com.pt account. Sigh! This should me much easier, Microsoft!

After going through all these hurdles, I managed to get my developer account and wrote my first mini-app: an XNA application that explores the device's accelerometer. It merely uses the accelerometer information to move a ball around the screen as you tilt the device (something that you have already seen). The accelerometer input in not treated in any special way so the movement you get is sluggish, just as if the ball is moving through molasses...

You can get the first sample from here.

The next version of the code will include more realistic ball movement, so there is some kinetics a dynamics stuff to review.

To help me in writing this tiny piece of code, I read the following articles:


Wednesday, January 19, 2011

Persisting Silverlight DataGrid sort descriptions

I came across this issue recently: how to persist Silverlight DataGrid sort descriptions between changes of the ItemsSource property? The DataGrid on version 4.0 does not expose a direct interface to manipulate the column sort descriptions although it somehow manages them internally. If you want to explicitly manage the column sort descriptions, you must use a PagedCollectionView container, through the SortDescriptions collection.

If you feed a PagedCollectionView to a DataGrid and then let the user change the column sort descriptions through the user interface (by clicking the column headers), the SortDescriptions collection will store the user changes. After realizing this, I devised a very simple strategy to persist the column sort descriptions whenever I needed to refresh the DataGrid:

  • If the data source is a PagedViewCollection, I just make a copy of the old SortDescriptions collection and apply it to the new PagedViewCollection object.
  • If the data source is just an IEnumerable, I create a new PagedViewCollection to wrap it and do the same as the previous point.

To make my life a bit easier, I created a very simple helper class with two private members:


private DataGrid dataGrid = null;
private PagedCollectionView pagedView = null;

The constructor simply stores the target DataGrid object reference:

public PersistDataGridSort(DataGrid dataGrid)
{
    this.dataGrid = dataGrid;
}

The bulk of the work is done in the SetItemsSource function that takes an object as parameter. This must be either an IEnumerable or a PagedCollectionView:

public void SetItemsSource(object collection)
{
    SortDescriptionCollection sortDescriptions = null;

    if(collection is PagedCollectionView)
    {
        if(pagedView != null)
        {
            sortDescriptions = new SortDescriptionCollection();

            foreach(SortDescription sortDescr in pagedView.SortDescriptions)
            {
                sortDescriptions.Add(sortDescr);
            }
        }
        pagedView = collection as PagedCollectionView;
        pagedView.SortDescriptions.Clear();
    }
    else if(collection is IEnumerable)
    {
        IEnumerable enumerable = collection as IEnumerable;

        if(pagedView != null)
            sortDescriptions = pagedView.SortDescriptions;
        pagedView = new PagedCollectionView(enumerable);
    }
    else
        throw new ArgumentException("Collection must be either a PagedCollectionView or an IEnumerable.");

    // Set the data grid's source
    dataGrid.ItemsSource = pagedView;

    // Reinstate the old sort descriptions
    if(sortDescriptions != null)
    {
        foreach(SortDescription sortDescr in sortDescriptions)
            pagedView.SortDescriptions.Add(sortDescr);
    }
}

To use this class, just create an instance using the target DataGrid and set its data source by calling this class' SetItemsSource method. Have fun!