Tuesday, 26 October 2010

Conf for PDC10 on Windows Phone 7

A first-cut of the PDC10 schedule can now be downloaded for the Windows Phone 7 version of Conf - now available on Marketplace (Zune link).

To download new conference data in Conf
  • Start on the first panel of the Panorama
  • Scroll down to other conferences... and touch Download more...
  • When the list downloads from the server, touch PDC10
  • PDC10 should appear in the list - if not, switch between the conferences until it does :-s
This is what the app looks like with PDC10 data loaded:

The iPhone version of Conf is currently awaiting AppStore approval - fingers crossed for Thursday!

Thursday, 14 October 2010

MonoTouch & WindowsPhone7: indexed lists

One interesting aspect of building cross-platform apps is how to adopt the 'standard' UI elements so that each app looks 'native'. A basic iPhone/MonoTouch and WindowsPhone7 application was introduced in a previous post. Each app uses the 'default' list representation.

This post is about making those apps easier to use, adding each platform's default "list index" to help select from long, sorted lists. The images below hardly need captions:
  • on the left is the iPhone app with alphabetic index down the right side of the screen
  • on the right is the WindowsPhone7 app showing the alphabet tiles 'in' the list, and the grid that is displayed when you touch one of those tiles

Implementing the two different solutions highlights the difference in the two platforms (referring of course to C#/MonoTouch on the iPhone, and C#/Silverlight on the WindowsPhone7). Get the complete code from github - the main changes for each platform are highlighted below:

iPhone (MonoTouch) UITableView sections

The following code was added to the UITableViewSource subclass to break up the list into sections, identify the section labels and wire up the alphabetic navigation. The GetCell and RowSelected methods also required a minor change.

List<string> sectionTitles;
Dictionary<int, <restaurant>> sectionElements = new Dictionary<int,restaurant>>();
public TableViewSource (List<restaurant> list, MainViewController controller)
   this.list = list;
   mvc = controller;
   sectionTitles = (from r in list
            orderby r.StartsWith
            select r.StartsWith).Distinct().ToList();
   foreach (var restaurant in list)
   {   // group elements together into 'alphabet'
      int sectionNumber = sectionTitles.IndexOf(restaurant.Name[0].ToString());
      if (sectionElements.ContainsKey(sectionNumber))
         sectionElements.Add(sectionNumber, new List<restaurant> {restaurant});
public override int NumberOfSections (UITableView tableView)
   return sectionTitles.Count;
public override string TitleForHeader (UITableView tableView, int section)
   return sectionTitles[section];
public override string[] SectionIndexTitles (UITableView tableView)
   return sectionTitles.ToArray();
public override int RowsInSection (UITableView tableview, int section)
   return sectionElements[section].Count(); //list.Count;

Windows Phone 7 'quick jump grid'

Although you'll see this kind of navigation in the 'built-in' applications, it isn't actually part of the default SDK. Thankfully Kevin Marshall has posted a quick jump grid sample which has been integrated into the RestGuide app - just add the relevant Assembly References then update the XAML to use the QuickJumpGrid (don't forget to add the relevant xmlns: declarations)

<cc:QuickJumpGrid DataSource="{Binding}"
        <local:RestaurantNameSelector />
           <StackPanel Margin="0,0,0,17" Width="432">
               <TextBlock Text="{Binding Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
               <TextBlock Text="{Binding Cuisine}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>

and implement this 'helper' class (which is referenced from the XAML)

namespace RestGuide
    public class RestaurantNameSelector : IQuickJumpGridSelector
        public Func<object, IComparable> GetGroupBySelector()
            return (p) => ((Restaurant)p).Name.FirstOrDefault();
        public Func<object, string> GetOrderByKeySelector()
            return (p) => ((Restaurant)p).Name;
        public Func<object, string> GetThenByKeySelector()
            return (p) => (string.Empty);