Creating WP7 prototypes with Sketchflow

With the upcoming release of Windows Phone Mango, you can create prototypes for Phone apps with Sketchflow. For people not knowing Sketchflow : it allows you to create prototypes that look like they have been drawn. When you present a “normal” prototype to a customer you get conversations like this :

Nice protoype, how long before you can deliver us the final product ?

I estimate we can deliver within 4 months.

What ? You created this prototype in just 3 days, it looks like it’s almost finished. How can it possibly take 4 months for completing ?

A sketchflow prototype looks more “unfinished”. It’s not new, it has been around for WPF and silverlight, but you can now also get the projecttemplate for WP7 for using in Blend. Just go to http://wp7sketchflow.codeplex.com/, download and install. Beware : you can only use this thing if you have the full paid version of Blend. The one you get for free with the phone developers tool will not do.

OK. Let’s open up Blend and create a Windows Phone SketchFlow application :

image

This project directly creates some an empty screen for my app  and a fake start-up screen:

image

I also get an overview how I can move (“Flow”) between the different screens:

image

I created a little prototype for an application I sometimes create during WP7-courses : a complaints-application for my city (the well-know megacity Serskamp in Belgium). This application allows me to signal stuff like defective traffic lights a.o. I also need to be able to add a location (GPS) and a picture, and to track my filed complaints. I’m not going to create the app itself now, but just the screens.

I start by adding a Panorama on my start screen. This thing automatically gets 2 Panorama-items. The design of my item looks like this :

image image

For the data I created a demo-datasource in the data-tab:

image 

got some trouble for designing the second Panorama-item. Unlike Visual Studio, in which you simply have to select a Panorama-item for making it the active one, there’s no such thing in Blend. Or at least I didn’t find it. The only thing I could do was temporary setting the visibility of the other items to collapsed.

Inside the Flow-panel I can select to add a new Connected screen. This way I create a screen for the follow-up of my complaints, and one for setting the location. I also create connections for returning to Screen 1, and remove the connection from my new screens to Search and AppList.

image

The Follow-up screen looks like this :

image

For finishing I also change the start-screen, and I’m done.

image

Now I’ve finished my SketchFlow-prototype, there’s 2 thing I can do : print it, or run it. In the File-menu you have an option for exporting to Word. This will export all your designs and add a table of contents :

WindowsPhonePrototype2.doc (1,28 mb) 

Creating a SketchFlow-prototype is essentially creating a Silverlight-application. This gives you a way of “running” the app, so you can demonstrate it to your customer (see video) :

 

 

Is that cool, or what ?

 

 



The return of SQL CE !

After playing a few weeks with the Mango-beta, I’m even more convinced that the Windows Phone 7 simply is the best smartphone available. Driving in your car, receiving a text-message, and suddenly a voice over Bluetooth  asks me if the message should be read! And after the message has been read, it asks if I would like to dictate an answer (or call). How cool is that ? (unfortunately only in English for the moment, so when trying to dictate in Dutch, you get funny results ).

One of the things that Mango brings is SQL Server CE. I remember using this on Windows Mobile, when you had to use stuff like SqlCeConnection, SqlCeCommand, etc… It seems that these classes are not existing on Mango, but of course we have Linq to SQL we can use. Using IsolatedStorageFile’s for storing data is nice, but having a “real” database for storing relational data is nicer. Still, during my experiment I saw that there are a few things missing to make life easier. It’s still in beta of course, so hopefully it will get added in the near future.

I wanted to do a little trial showing the products and Categories out of the NorthWind-database. I decided to use SQL Integration Services for creating a SQL CE database for me, copying the needed data. Unfortunately this is not possible for CE. I needed to create the database and the tables myself. In the beta-version of Mango developer-tools it is yet impossible to select a SQLCE-file for item to add. I simply created it in a dummy console-app, and then copied it into my WP7-application. Double clicking on the sdf-file opens up the designer.

image

Adding a table is easy: Right-click the Tables-folder, select “Create Table” and you can start designing. This is what I created :

image

Specifying the Primary Key and the relationship between Products and Categories can be created by calling the table properties:

image

So far for the database structure. Copying the data from the “normal” Northwind to my CE-tables can be done through SQL Integration services. Now what about the LINQ to SQL classes ? No way of adding such an item in my project. The way to go, is like in the beginning of LINQ: use SQLMetal (You’ll find it here : C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin). The following command generates the necessary code:

Sqlmetal /code:NorthWindCE.cs Northwind.sdf

 

The generated code look nice, but if your looking for any navigation-properties: nowhere to find…

Next roadblock: I can only access databases stored in isolatedstorage. Makes sense, although it would be nice to be able to share data over multiple apps. Since there is no direct way of adding files for IsolatedStorage in VisualStudio, I wrote a bit of code for copying my sdf-file (which has been added as a resource) to IsolatedStorage:

   1:  private void CheckIsolatedStorageDb()
   2:  {
   3:      var storage = IsolatedStorageFile.GetUserStoreForApplication();
   4:      if (!storage.FileExists("NorthWind.sdf"))
   5:      {
   6:          Uri uri = new Uri("SQLTest;component/NorthWind.sdf",UriKind.Relative);
   7:          StreamResourceInfo info = App.GetResourceStream(uri);
   8:   
   9:          if (info!=null)
  10:          {
  11:              Stream stream = info.Stream;
  12:              BinaryReader reader = new BinaryReader(stream);
  13:              byte[] buffer = new byte[stream.Length];
  14:              reader.Read(buffer, 0, Convert.ToInt32(stream.Length));
  15:              reader.Dispose();
  16:   
  17:              IsolatedStorageFileStream iStream= storage.CreateFile("NorthWind.sdf");
  18:              iStream.Write(buffer, 0, buffer.Length);
  19:              iStream.Flush();
  20:              iStream.Dispose();
  21:              stream.Dispose();
  22:          }
  23:      }
  24:  }

 

I call this function on Application_launch, and my sdf-file gets copied.  From now on I can start using my db, using LINQ. Let’s start by adding a listbox to our MainPage like this:

<ListBox DisplayMemberPath="ProductName" ItemsSource="{Binding}" />

 

Code looks like this :

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
    db = new NorthWind("Data Source=isostore:/NorthWind.sdf");
 
    this.DataContext = from p in db.Products
                       where p.UnitPrice < 20
                       select p;    
}

As you can see, I provide a connectionstring pointing to Isolated storage, binding the datacontext to some LINQ-statement, and voila.

Now what about navigating between categories and products ? First I extend my SQLmetal-generated code with these (copied these by generating code for the “big” Northwind) :

In Products:

   1:  private EntityRef<Categories> _Category;
   2:   
   3:  [global::System.Data.Linq.Mapping.AssociationAttribute(Name = "Category_Product", Storage = "_Category",
   4:      ThisKey = "CategoryID", OtherKey = "CategoryID", IsForeignKey = true)]
   5:  public Categories Category
   6:  {
   7:      get
   8:      {
   9:          return this._Category.Entity;
  10:      }
  11:      set
  12:      {
  13:          Categories previousValue = this._Category.Entity;
  14:          if (((previousValue != value)
  15:                      || (this._Category.HasLoadedOrAssignedValue == false)))
  16:          {
  17:              this.SendPropertyChanging();
  18:              if ((previousValue != null))
  19:              {
  20:                  this._Category.Entity = null;
  21:                  previousValue.Products.Remove(this);
  22:              }
  23:              this._Category.Entity = value;
  24:              if ((value != null))
  25:              {
  26:                  value.Products.Add(this);
  27:                  this._CategoryID = value.CategoryID;
  28:              }
  29:              else
  30:              {
  31:                  this._CategoryID = default(Nullable<int>);
  32:              }
  33:              this.SendPropertyChanged("Category");
  34:          }
  35:      }
  36:  }

And in Categories:

   1:  private EntitySet<Products> _Products;
   2:   
   3:  [global::System.Data.Linq.Mapping.Association(Name="Category_Product", Storage="_Products",
   4:      ThisKey="CategoryID", OtherKey="CategoryID")]
   5:  public EntitySet<Products> Products 
   6:  {
   7:      get { return this._Products; }
   8:      set { this._Products.Assign(value); }
   9:  }

 

  • Let’s now change our MainPage a little: I’ll have two Listboxes this time:
<ListBox DisplayMemberPath="CategoryName" Name="listBox2" ItemsSource="{Binding}" />
<ListBox Grid.Row="1" Name="listBox1" DataContext="{Binding ElementName=listBox2, Path=SelectedItem}"
         DisplayMemberPath="ProductName" ItemsSource="{Binding Products}" />

 

Also set the datacontext to categories this time :

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
    db = new NorthWind("Data Source=isostore:/NorthWind.sdf");
 
    this.DataContext = db.Categories;            
}

And thanks to the powers of databinding, I get all products from the category I select.

image

Now I’m already happy to have this in the beta, but I’d like to have some extras in the final version:

  • - Give me an easy way of copying existing structures to my CE database
  • - Get me a way of creating my LINQ to SQL classes from within Visual Studio
  • - Make sure that my Navigation properties are being generated
  • - and give me something, so I can specify files to be directly saved in Isolated Storage. (Some Build Action ? Next to Resource, Content,… also an option IsolatedStorage ?)