Sunday, March 18, 2012

Using files as your app data

In Windows 8, you can use your files as data for your app. Suppose you have a bunch of pics stored on your machine or on your network, for example. You can easily display them in your Metro app :
Here’s the basic method behind this UI :
   1: private async Task GetFilesAsync(IStorageFolder rootFolder)
   2: {
   3:     myFiles.Clear();
   5:     var files = await rootFolder.GetFilesAsync();
   7:     foreach (var f in files)
   8:     {
   9:         var myFile = new MyFile { FileName = f.Name };
  11:         myFile.Thumbnail = await (f as StorageFile).GetThumbnailAsync(
  12:             ThumbnailMode.ListView, 100, ThumbnailOptions.ResizeThumbnail);
  14:         myFiles.Add(myFile);
  15:     }
  16: }

It uses a data model file that looks something like this :

   1: public class MyFile : BindableBase
   2: {
   3:     public string FileName { get; set; }
   5:     string title;
   6:     public string Title 
   7:     {
   8:         get { return title; }
   9:         set { SetProperty<string>(ref title, value); }
  10:     }
  12:     public StorageItemThumbnail Thumbnail { get; set; }
  13: }

A custom file class that stores the file name, title (set by the user on her pictures) and thumbnail to display. Note it extends BindableBase for convenience to easily implement INotifyPropertyChanged and raise UI notifications but simply calling SetMethod(), defined in BindableBase.

Also note the GetFilesAsync method asynchronously retrieves the thumbnail of each pic by calling GetThumbnailAsync. How easy is that ? Thanks winRT.

Now suppose you want to group the pics in some way. You can do it easily through the pivot API, which creates virtual folders that represent groups. Here’s another method :

   1: private async Task GetVirtualFoldersAsync(StorageFolder rootFolder)
   2: {
   3:     myVirtualFolders.Clear();
   5:     var pivot = CommonFolderQuery.GroupByMonth;
   6:     var queryOptions = new QueryOptions(pivot);
   8:     var queryResult = rootFolder.CreateFolderQueryWithOptions(queryOptions);
   9:     var vFolders = await queryResult.GetFoldersAsync();
  11:     foreach (StorageFolder vfolder in vFolders)
  12:     { 
  13:         var myFolder = new MyFolder { FolderName = vfolder.Name };
  15:         var files = await vfolder.GetFilesAsync();
  16:         myFolder.ImageCount = files.Count();
  18:         myFolder.Thumbnail = await (vfolder as StorageFolder).GetThumbnailAsync(
  19:             ThumbnailMode.ListView, 200, ThumbnailOptions.ResizeThumbnail);
  21:         myVirtualFolders.Add(myFolder);
  22:     }
  23: }

What this method does is generate a list of virtual folders each matching a group of pics taken during a given month. The pivot is defined using the GroupByMonth query, which will result in the files being pivoted on using this criterion. We could have picked another pivot, such as CommonFolderQuery.GroupByAuthor for example.

Next we call CreateFolderQueryWithOptions(options) to actually create the pivoted query. This method is available on the StorageFolder passed into the method, for example Windows.Storage.KnownFolders.PicturesLibrary.  Then we call GetFoldersAsync to actually dig and retrieve the files grouped by month.

Once the method completes, you can access the list of virtual folders representing the groups created. Here this is done in the foreach loop which loops over the virtual folders. My code then goes on to do app-specific stuff, such as retrieving the list of files in the group (vfolder) so as to display the count in the UI, and retrieve the vfolder’s thumbnail. Windows does that for you, it will generate a thumbnail for your folder or virtual folder, usually the thumbnail of the first pic in the folder. So you can call GetThumbnailAsync on a StorageFile OR a StorageFolder. Awesome.

Like before, I instantiate a custom class to store the vfolder data and store it in an observable collection so my UI can bind to it and get change notified. The UI then lists groups (vfolders), and I can add code so that when a Vfolder thumbnail is tapped, the list of actual pics in that vfolder gets displayed.


So you can see how easy it is to use files as app data and then implement simple pivots on that data. The beauty of this is the way we perform asynchronous operations, which would have previously made a hellish mess in our code, so smoothly and easily using async / await. Thanks to this new pattern the work we need to do to define and implement pivots on top of file resources in our data apps is almost fun!

Happy pivoting

No comments:

Post a Comment