Background Audio #win8dev #winrt

In this post I am going to detail some of the work I have been doing on Background Audio. But before I get onto it, let me say that the last few months have been crazy / busy, not highly motivational for personal dev etc. I have done a few updates over the last few months but no new development until this month.

About 2 weeks back I started work on Porting Slydr code to WPF control and that was a breeze. Infact last night I saw something about a simple app being tested.. makes me think on whether I should beat them to it :) or not.

Now back to Background Audio. With Windows Phone, one had to create a Background Audio Player which the app and system would then communicate with. The app could kick the Background Audio Player off and then exit and the audio would keep on playing. I have talked about this before and will saying it again. WPDev 7x provided many ways of playing audio. With Windows 8 and #WinRT your options are restricted. I have gotten used to giving MediaElement more usage and credit for what it does.

<MediaElement x:Name="mePlayer" />

All you need to do is set the Source property and then call Play(). The audio starts playing. If the app gets suspended, the music stops playing. To enable background audio there are a number of things you need to do.
* Firstly set MediaElement‘s AudioCategory to BackgroundCapableMedia. This still doesn’t activate the Background Audio as its only the first step

* Now open package.appmanifest file. Open the Declarations tab and add Background Tasks. While you are there set the Supported task types property to Audio and Control Channel. You will also need to set the Start page in App settings. Of course now that you have done this, you will have to create a Badge logo before you can save the changes to appmanifest.
appManifest

* Now back to codebehind of your page and add event handlers for MediaControl‘s PlayPressed, PausePressed, StopPressed and PlayPauseTogglePressed events

In my app I also support Previous Track / Next Track so I additionally added support for PreviousTrackPressed and NextTrackPressed events.

MediaControl.PlayPressed += MediaControl_PlayPressed;
MediaControl.PausePressed += MediaControl_StopPressed;
MediaControl.StopPressed += MediaControl_StopPressed;
MediaControl.PlayPauseTogglePressed += MediaControl_PlayPauseTogglePressed;
MediaControl.NextTrackPressed += MediaControl_NextTrackPressed;
MediaControl.PreviousTrackPressed += MediaControl_PreviousTrackPressed;

and

void MediaControl_PreviousTrackPressed(object sender, object e)
{
    this.Previous();
}

void MediaControl_NextTrackPressed(object sender, object e)
{
    this.Next();
}

void MediaControl_PlayPauseTogglePressed(object sender, object e)
{
    if (MediaControl.IsPlaying)
        this.Stop();
    else
        this.Play();
}

void MediaControl_StopPressed(object sender, object e)
{
    this.Stop();
}

void MediaControl_PlayPressed(object sender, object e)
{
    this.Play();
}

Now when you run the app, initiate the audio playback and navigate away from the app.. Bingo. the audio is still playing.

Slides and Sample Code from Async Task talk

I have uploaded sample from from my async task talk I did last week on github.
https://github.com/hermitdave/AsyncTask

Here is the slide from the talk – Async Programming.

I started by talking about Event based async.. how framework converted sync WCF methods into event driven async methods when one adds a reference for Silverlight or Winddows Phone or Windows 8 projects. I further explained that if you had multiple dependent calls and how async task might actually help.

Next up for a very simple explanation of async task. how async task code creates a dynamic structure which is used to execute the actual code. I mentioned how async task is run on the same thread the current execution is suspended. This raised many questions.. I tried to unsatisfactorily explain the mechanism (by the looks of it). The idea was to talk through individual samples. So next I fired up App and VS and talked individual samples.

There was a hairy project moment when I was trying to show multi-threading using async task.

I think it was okay.. maybe I should have chosen an easier subject ? maybe I just need to sound more convincing next time. I am also going to have comparable async event samples side by side. There were some comments. 1st one was the same day.. very critical comment suggesting that I knew nothing (as I said async does not result in creation of new threads for execution of the said code). The chap further critisied my samples are overly simple.. and finally my projector skills (issues during the last part of event).

Oh well.. Should I continue talking on the subject ?

Implement Search Contract the easy way #win8dev

Most apps contain some sort of data that you as a developer would like exposed. That’s were the Search Contract comes into play. Say the user is on the start screen and wishes to search your app, they could just start typing and select your app from the list. If you implemented Search contract, your app will be listed in the app list and the user could just type away and hit enter to see results. That would be nice wouldn’t it ?

Lets get on with it and add search contract in a simple / easy way.
Right click on the Win8 project and select Search Contract. Name it whatever you wish and hit enter.

This does two things:

  • Adds override for OnSearchActivated in your App.xaml.cs
  • Adds required page for search and display of results.

This is what the OnSearchActivated looks like

protected async override void OnSearchActivated(Windows.ApplicationModel.Activation.SearchActivatedEventArgs args)
{
    // TODO: Register the Windows.ApplicationModel.Search.SearchPane.GetForCurrentView().QuerySubmitted

    // event in OnWindowCreated to speed up searches once the application is already running

    // If the Window isn't already using Frame navigation, insert our own Frame
    var previousContent = Window.Current.Content;
    var frame = previousContent as Frame;

    // If the app does not contain a top-level frame, it is possible that this 
    // is the initial launch of the app. Typically this method and OnLaunched 
    // in App.xaml.cs can call a common method.
    if (frame == null)
    {
        // Create a Frame to act as the navigation context and associate it with
        // a SuspensionManager key
        frame = new Frame();
        Cineworld.Common.SuspensionManager.RegisterFrame(frame, "AppFrame");

        if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
        {
            // Restore the saved session state only when appropriate
            try
            {
                await Cineworld.Common.SuspensionManager.RestoreAsync();
            }
            catch //(Cineworld.Common.SuspensionManagerException)
            {
                //Something went wrong restoring state.
                //Assume there is no state and continue
            }
        }
    }

    frame.Navigate(typeof(SearchResults), args.QueryText);
    Window.Current.Content = frame;

    // Ensure the current window is active
    Window.Current.Activate();
}

as you can see it is passing the search query to the Search Results page while navigating.
Now lets look at the code-behind in SearchResults.xaml.
FYI, I am loading my dataset if required in the OnNavigatedTo method. This page is a simple results display page. It contains GridView / ListView to display results. Lets look at the LoadState method

protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
    var queryText = navigationParameter as String;

    List<SearchResult> matches = new List<SearchResult>();

    foreach (var f in App.Films.Values)
    {
        IEnumerable<CastInfo> casts = from cast in f.FilmCast
                                        where cast.Name.StartsWith(queryText, StringComparison.CurrentCultureIgnoreCase)
                                        select cast;

        foreach (var c in casts)
        {
            //searchCinemas.Add(c.Name, c);
            matches.Add(new SearchResult() { Name = c.Name, Subtitle = String.Format("{0} in {1}", c.Character, f.Title), SearchObject = f, Image = c.ProfilePath });
        }
    }

    IEnumerable<FilmInfo> films = from film in App.Films.Values
                                    where film.Title.StartsWith(queryText, StringComparison.CurrentCultureIgnoreCase)
                                    select film;

    searchFilms.Clear();
    searchCinemas.Clear();

    foreach (var f in films)
    {
        searchFilms.Add(f.Title, f);
        matches.Add(new SearchResult() { Name = f.Title, Image = f.PosterUrl, SearchObject = f });
    }

    IEnumerable<CinemaInfo> cinemas = from cinema in App.Cinemas.Values
                                        where cinema.Name.StartsWith(queryText, StringComparison.CurrentCultureIgnoreCase)
                                        select cinema;

    foreach (var c in cinemas)
    {
        searchCinemas.Add(c.Name, c);
        matches.Add(new SearchResult() { Name = c.Name, SearchObject = c, Image = new Uri("ms-appx:///Assets/Background.png") });
    }
            
    // TODO: Application-specific searching logic.  The search process is responsible for
    //       creating a list of user-selectable result categories:
    //
    //       filterList.Add(new Filter("<filter name>", <result count>));
    //
    //       Only the first filter, typically "All", should pass true as a third argument in
    //       order to start in an active state.  Results for the active filter are provided
    //       in Filter_SelectionChanged below.

    // Communicate results through the view model
    this.DefaultViewModel["QueryText"] = '\u201c' + queryText + '\u201d';

    bAllowNav = false;

    this.DefaultViewModel["Results"] = matches;

    bAllowNav = true;

    var filterList = new List<Filter>();
    filterList.Add(new Filter("All", 0, true));

    //this.DefaultViewModel["Filters"] = filterList;
    //this.DefaultViewModel["ShowFilters"] = filterList.Count > 1;
}

I added code to search my dataset and to add results to DefaultViewModel. I don’t use MVVM but the default code implemented basic binding etc and I thought I’d leave it at that. I accumulate the results and save them and let bindings do the rest. Let me show you how it looks
Say I got to start screen, type I ben and select my app, this is what I get.

Now you have a nice list of matched entries. Now suppose I wanted to let users click on a matched entry and to navigate them to details page ? I implemented GridView ItemClick event (SelectionChanged doesn’t work for some reason)

private void resultsGridView_ItemClick(object sender, ItemClickEventArgs e)
{
    if (e.ClickedItem != null && bAllowNav)
    {
        SearchResult res = (SearchResult)e.ClickedItem;
        if (res.SearchObject is FilmInfo)
        {
            FilmDetails.SelectedFilm = (res.SearchObject as FilmInfo);
            this.Frame.Navigate(typeof(FilmDetails));
        }
        else if (res.SearchObject is CinemaInfo)
        {
            CinemaDetails.SelectedCinema = (res.SearchObject as CinemaInfo);
            this.Frame.Navigate(typeof(CinemaDetails));
        }
    }
}

Hope this post is helpful to others looking to implement the search contract. Happy coding!

#async task and the for loop bug

I have used various flavours of async task implementation.
* WP7 / async CTP / v3 VS 2010
* Win8 / VS 2012
* Azure / VS 2012
* SL / async targetting pack / VS 2012

I blogged about how i had issues with #async on #aszure and funnily enough i wasn’t the only one. As discussed in http://invokeit.wordpress.com/2012/11/07/windows-azure-and-async-task-mechanism-async/ if you use something like this

AsyncDataSourceObj aeo = new AsyncDataSourceObj();

protected async Task BuildFilmDataSet()
{
    Films films = await aeo.GetFilmData();
    foreach(var film in films)
    {
        Cinemas cinemas = await aeo.GetCinemaData(film);

        // do things

        // do more things 
    }
}

It doesn’t work and a little investigation showed me that i wasn’t doing anything wrong.

The moment await aeo.GetCinemaData(film); gets called, the execution instead of awaiting moves to the next iteration of for loop. Why in the world you would want that ? I am sure if you wanted that one would have used Parallel.For instead.

For some reason, the creators thought that we clever people wouldn’t ever want to do a async call in for loop. I mean its not like its the most common loop usage etc…

The suggestion is to use Task.Yield() (or TaskEx.Yield) within for loop

It however doesn’t always work. I have tried it with my last Silverlight + Async Targetting pack and its still the same. Infact I had to revert to event based async in that case.

Here’s a screen of azure sample in action

Windows Azure and Async Task mechanism #async

I know most of you are probably sick and tired of my experiences with Async.

Since i had so much fun with async on Windows Phone and on Windows 8 dev, i decided to use my azure account and to build data repo there. In simple terms, i do this on azure

  • Get a list of objects – e.g. film list
  • for each film in the above list, query other services for addtional data.
  • persist the data.

The implementation i did was simple.. Create a project with Azure services and add WorkerRole to it.
In worker role, use async like we know

AsyncDataSourceObj aeo = new AsyncDataSourceObj();

protected async Task BuildFilmDataSet()
{
    Films films = await aeo.GetFilmData();
    foreach(var film in films)
    {
        Cinemas cinemas = await aeo.GetCinemaData(film);

        // do things

        // do more things 
    }
}

This doesn’t work as you’d imagine. Within the foreach loop, once await is called, the execution instead of waiting for it to complete, goes to the next iternation of foreach and it fails for some reason.

Now you know how much i love calling Wait() on async.. so what did i do ? well its not a time critical thing i am doing here and i do not mind blocking the thread worker role is running on.

AsyncDataSourceObj aeo = new AsyncDataSourceObj();

protected async Task BuildFilmDataSet()
{
    Task<Films> tfilms = aeo.GetFilmData();
    tfilms.Wait();

    if(!tfilms.IsFaulted && tfilms.Result != null)
    {
        foreach(var film in tfilms.Result)
        {
            Task<Cinemas> tcinemas = aeo.GetCinemaData(film);
            tcinemas.Wait();

            // do things

            // do more things 
    }
}

Now it works as you’d expect. If you ever get stuck in similar situation, you know what to do next!!

Async Task mechanism and OnNavigatedTo Part 2 #win8dev

Previously i discussed issues i had with #win8dev and #wpdev and using async task mechanism – http://invokeit.wordpress.com/2012/10/15/async-await-and-onnavigatedto-wpdev-win8dev/. With #wpdev you have to consume that mechanism as long as you use async CTP.

So how does one go about doing it in #win8dev #winrt correctly ? We start by marking all methods as async (in this case OnNavigatedTo. If we were firing mutilple calls and possibly making UI calls, #win8dev async implementations is a breeze.

AsyncDataSourceObj aeo = new AsyncDataSourceObj();
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
    bErrored = false;
    try
    {
        MyDataType1 mydata1 = await aeo.UseAsyncAwaitStyleCall1();
        MyDataType2 mydata2 = await aeo.UseAsyncAwaitStyleCall2();
        MyDataType3 mydata3 = await aeo.UseAsyncAwaitStyleCall3();
    }
    catch
    {
        bErrored = true;
    }

    if(bErrored)
    {
        await (new MessageDialog("Error")).ShowAsync();
    }
    else
        // process data however you want.
}

above however isn’t a very good implementation as it chains various tasks. you dont want to do this unless the second call depends on the first etc. so if you have distinct calls, one can do this

AsyncDataSourceObj aeo = new AsyncDataSourceObj();
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
    bErrored = false;
    try
    {
        List mytasklist = new List();
        mytasklist.Add(aeo.UseAsyncAwaitStyleCall1());
        mytasklist.Add(aeo.UseAsyncAwaitStyleCall2());
        mytasklist.Add(aeo.UseAsyncAwaitStyleCall3());

        await Task.WhenAll(mytasklist);
    }
    catch
    {
        bErrored = true;
    }

    if(bErrored)
    {
        await (new MessageDialog("Error")).ShowAsync();
    }
    else
        // process data however you want.
    // process data however you want.
}

the idea as explained to me by Oren after being told off by Matt is that you leave it to underlying implementation to use whatever it has rather than hacking around with it.

the code as a result is cleaner and works just as well :) What exactly does WhenAll do.. well it asks async task implementation to continue execution when all the tasks in the list are completed. The good part is that its a non blocking call. There’s also WhenAny which continues execution when one of the tasks in the list has completed.

Try and avoid WaitAny or WaitAll as both are blocking calls.

In case of #wpdev it implementation with async ctp was basic and one has to use hacks unforunately. we shall see what Async Targeting Pack brings to #wpdev party in a bit

Just for the record, you might not want to just chuck the exception away.. you should try and log it for future reference as it could be an issue thats just surfacing. have a look at MetroLog on nuget or if you like source, go github

Embed / use custom font in Windows 8 Store apps #win8dev #winrt

I was supposed to blog earlier but forgot. Saw a question on Stackoverflow and thought.. now is the time. So how does one embed fonts ?
Well just include them in project as Content files.

How do you use them.. here is how

<ComboBox x:Name="cbFont" Width="230" Margin="0, 10, 0, 0" Foreground="Black" Background="Gray" SelectionChanged="cbFont_SelectionChanged">
     <ComboBoxItem Content="12:34" FontFamily="Assets/Fonts/akka.ttf#Akka" />
     <ComboBoxItem Content="12:34" FontFamily="Assets/Fonts/alghorie neue.ttf#alghorie neue" />
     <ComboBoxItem Content="12:34" FontFamily="Assets/Fonts/Alpha Mutation.ttf#Alpha Mutation" />
     <ComboBoxItem Content="12:34" FontFamily="Assets/Fonts/AlphaFlowers.ttf#AlphaFlowers" />
     <ComboBoxItem Content="12:34" FontFamily="Assets/Fonts/AMSTRG__.TTF#Ams Trame" />
     <ComboBoxItem Content="12:34" FontFamily="Assets/Fonts/ARCADE_I.TTF#Arcade Interlaced" />
     <ComboBoxItem Content="12:34" FontFamily="Assets/Fonts/ARCADE_R.TTF#Arcade Rounded" />
</ComboBox>

You dont have to use combo box you can use anything.. i use it with TextBlock etc as well. Just remember. After the font file name, you need to put the font name itself. Thats all

Async await and OnNavigatedTo #wpdev

Update: this only applies to #wpdev and using async CTP for async task mechanism. I have had a lot of feedback and after a bit of rework, i can do it right in #win8dev. see this post http://invokeit.wordpress.com/2012/10/24/async-task-mechanism-and-onnavigatedto-part-2-win8dev/

I am sure i am not the only one with bad coding habits. Maybe its just me or maybe i am more common than i’d like to think but here’s how i deal with loading data i require per page.

When a XAML page is called, i tend to override OnNavigatedTo event. This is where i put all the calls to load / fire data. If i am going to make web service calls or read from storage, it tends to happen in OnNavigatedTo method.

Over the last few months, i have migrated 2 of my apps from Windows Phone to Windows 8 and for the 3rd, i have taken a slightly different approach. Instead of jumping straight and porting it, i put the app in #WPDev under scissors and i am making code easily shareable between the two.

Step 1: Install Async CTP for VS 2010 (make sure you pray to whatever thing you believe in).. if that doesn’t work.. try threatening whatever thing you believe in.. if you are lucky Async CTP might just install :)

Step 2: Convert event driven async code to async await type code. For WebClient i found a helper class, you can download it here http://softwareblog.alcedo.com/post/2012/01/25/TaskCompletionSource-in-real-life-(part-2-of-2).aspx. It exposes awaitable Web Client and I used that to convert all other Event drive code to Task driven code

Here’s where the problem started. I tend to fire off the async event driven calls in OnNavigatedTo
If i change it to async await.. it doesn’t really work (at least not how i want it to). I have noticed the same with async await on Windows 8.

AsyncDataSourceObj aeo = new AsyncDataSourceObj();
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    aeo.UseEventStyleCallCompleted += OnUseEventStyleCallCompleted;
    aeo.UseEventStyleCall();
}

private void OnUseEventStyleCallCompleted( /* args */ )
{
    // show the data
    // make sure you use Dispatcher when touching UI objects
}

Now suppose we modified the above code to use async await

AsyncDataSourceObj aeo = new AsyncDataSourceObj();
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
    MyDataType mydata = await aeo.UseAsyncAwaitStyleCall();

    // now show the data.
}

This doesn’t seem to work correctly… maybe because i am declaring OnNavigatedTo async or maybe because i am making it pause and continue in a fashion it wasn’t supposed to… well i got tired eventually and this is what i settled for something that looks like this

AsyncDataSourceObj aeo = new AsyncDataSourceObj();
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    ThreadPool.QueueUserWorkItem(new WaitCallback(f =>
    {
        Task<MyDataType> tmydata = aeo.UseAsyncAwaitStyleCall();
        tmydata.Wait();

        // now show the data.
        // use dispatcher to manipulate UI controls
    }));
}

this is a compromise between a purist Async Await usage and actually doing things the way i like it. And just FYI, it works beautifully

I haven’t done any hacks.. these methods are exposed.. i have just spawned off the async wait on a Threadpool thread myself.. sure the system could have done it but someone it didn’t like the way i did it. Oh well

Porting Windows Phone App to Windows 8 #wpdev #win8dev

The main message of HHGTG was “Don’t Panic”. It’s universally applicable and the case for porting you WP app to Windows 8 is no different. As WP Devs, we are already used to restrictions on what can and cannot be done. Windows 8 is a different beast that uses the same idea but being a full-blown OS, APIs exposed are different.

Windows Phone API is Silverlight API. Windows 8 has native support for XAML & HTML5. The API available to developers are WinRT and can be used from C++/CX, .NET and JS. I am going to discuss porting a C# Silverlight Windows Phone App to Windows 8. There are two parts to porting story. Get the code working and adapting the user interface. Getting the code working is the easy part. Adapting the UI slightly a bit tricky. Let’s get started

Code Porting – the easy way

Like many, I prefer to do just about everything the easy way. How do I go about it ? Well I take chunks of code and I move it between projects.

1) Custom Controls:

If you use custom controls, you might have to port some of them. A lot of controls have equivalents. If you use ListPicker or LongListSelector from Silverlight Toolkit, try ComboBox. I used AutoCompleteBox and had to write my own. If source is available, porting control is easy. In another project, I ported coding 4 fun toolkits Hexagon Color Picker.

2) XAML:

Start with the basic grid and build your xaml by pulling chunks from Windows Phone project. Most xaml with exception of certain controls can be copied. I have migrated storyboard animations etc no issues.

3) C# code:

    1. WinRT development like WP Dev requires use of asynchronous mechanism however the native WinRT API prefers to use async Task mechanism. Any methods making system calls need to be async and APIs need to be waited for.
      Read more about async programming on msdn http://msdn.microsoft.com/en-us/library/hh191443.aspx
    2. Storage:
      •   IsolatedStorageFile
      •   IsolatedStorageSettings
      public static void GetLevelData(DictionaryDef dict, int Level)
      {
          if (dict != DictionaryDef.NotSet)
          {
              App.WordList.Clear();
              App.WordDict.Clear();
      
              string File = GetLevelFile(dict, Level);
      
              Uri uriPaths = new Uri(File, UriKind.RelativeOrAbsolute);
      
              StreamResourceInfo sriPaths = System.Windows.Application.GetResourceStream(uriPaths);
      
      
              using (StreamReader sr = new StreamReader(sriPaths.Stream))
              {
                  string l;
                  while ((l = sr.ReadLine()) != null)
                  {
                      if (!String.IsNullOrWhiteSpace(l))
                      {
                          App.WordList.Add(l);
                          App.WordDict.Add(l, 0);
                      }
                  }
              }
          }
      }
      
      public class PersistHelper
      {
          public static T LoadObjectFromStorage<T>()
          {
              T ObjToLoad = default(T);
      
              try
              {
                  using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
                  {
                      if (isf.FileExists(GetFileName<T>()))
                      {
                          using (IsolatedStorageFileStream fs = isf.OpenFile(GetFileName<T>(), System.IO.FileMode.Open))
                          {
                              XmlSerializer ser = new XmlSerializer(typeof(T));
                              ObjToLoad = (T)ser.Deserialize(fs);
                          }
                      }
      
                  }
              }
              catch (Exception error)
              {
                  throw new NotImplementedException(error.Message);
              }
      
              return ObjToLoad;
          }
      
          public static void SaveObjectToStorage<T>(T ObjectToSave)
          {
              TextWriter writer;
      
              using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
              {
                  using (IsolatedStorageFileStream fs = isf.OpenFile(GetFileName<T>(), System.IO.FileMode.Create))
                  {
                      writer = new StreamWriter(fs);
                      XmlSerializer ser = new XmlSerializer(typeof(T));
                      ser.Serialize(writer, ObjectToSave);
                      writer.Close();
                  }
              }
          }
      
          public static string GetFileName<T>()
          {
              return typeof(T).FullName + ".xml";
          }
      
          public static bool IsObjectPersisted<T1>()
          {
              using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
              {
                  return isf.FileExists(GetFileName<T1>());
              }
          }
      
          public static T LoadSetttingFromStorage<T>(string Key)
          {
              T ObjToLoad = default(T);
      
              if (IsolatedStorageSettings.ApplicationSettings.Contains(Key))
              {
                  ObjToLoad = (T)IsolatedStorageSettings.ApplicationSettings[Key];
              }
      
              return ObjToLoad;
          }
      
          public static void SaveSettingToStorage(string Key, object Setting)
          {
              if (!IsolatedStorageSettings.ApplicationSettings.Contains(Key))
              {
                  IsolatedStorageSettings.ApplicationSettings.Add(Key, Setting);
              }
              else
              {
                  IsolatedStorageSettings.ApplicationSettings[Key] = Setting;
              }
          }
      
          public static bool IsSettingPersisted(string Key)
          {
              return IsolatedStorageSettings.ApplicationSettings.Contains(Key);
          }
      }
      
      •   StorageFile / StorageFolder.
      •   Get access to .NET streams using above
      •   Package.Current.InstalledLocation.Path – for   reading content files
      •   ApplicationData.Current provides LocalFolder,   RoamingFolder & TempFolder
      •   ApplicationData.Current provides LocalSettings   & RoamingSettings
      •   RoamingFolder / RoamingSettings shared between   devices.
      public static async void GetLevelData(DictionaryDef dict, int Level)
      {
          if (dict != DictionaryDef.NotSet)
          {
              App.WordDict.Clear();
      
              string File = Path.Combine(Package.Current.InstalledLocation.Path, GetLevelFile(dict, Level));
      
              StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(Path.GetDirectoryName(File));
      
              using (Stream s = await folder.OpenStreamForReadAsync(Path.GetFileName(File)))
              {
                  using (StreamReader sr = new StreamReader(s))
                  {
                      string l = null;
                      while (true)
                      {
                          l = sr.ReadLine();
                          if (l == null)
                              break;
      
                          if (l.Length > 0)
                              App.WordDict.Add(l, null);
                      }
                  }
              }
          }
      }
      
      public class PersistHelper
      {
          //private static StorageFolder storageFolder = Windows.Storage.ApplicationData.Current.RoamingFolder;
          //private static ApplicationDataContainer storageSettings = ApplicationData.Current.LocalSettings;
      
          private async static Task GetFileIfExistsAsync(StorageFolder folder, string fileName)
          {
              try
              {
                  return await folder.GetFileAsync(fileName);
      
              }
              catch
              {
                  return null;
              }
          }
      
      
          public static async Task LoadObjectFromStorage(Windows.Storage.StorageFolder storageFolder)
          {
              T ObjToLoad = default(T);
      
              try
              {
                  StorageFile storageFile = await storageFolder.CreateFileAsync(GetFileName(),
                      CreationCollisionOption.OpenIfExists);
      
                  using (Stream inStream = await storageFile.OpenStreamForReadAsync())
                  {
                      XmlSerializer serializer = new XmlSerializer(typeof(T));
                      ObjToLoad = (T)serializer.Deserialize(inStream);
                  }
              }
              catch (Exception error)
              {
                  throw new NotImplementedException(error.Message);
              }
      
              return ObjToLoad;
          }
      
          public static async void SaveObjectToStorage(T ObjectToSave, Windows.Storage.StorageFolder storageFolder)
          {
              string filename = GetFileName();
      
              using (Stream fs = await storageFolder.OpenStreamForWriteAsync(filename, CreationCollisionOption.ReplaceExisting))
              {
                  using (StreamWriter sw = new StreamWriter(fs))
                  {
                      XmlSerializer ser = new XmlSerializer(typeof(T));
                      ser.Serialize(sw, ObjectToSave);
                  }
              }
          }
      
          public static string GetFileName()
          {
              return typeof(T).FullName + ".xml";
          }
      
          public async static Task IsObjectPersisted(Windows.Storage.StorageFolder storageFolder)
          {
              string file = GetFileName();
      
              StorageFile storageFile = await GetFileIfExistsAsync(storageFolder, file);
      
              return (storageFile != null);
          }
      
          public static T LoadSetttingFromStorage(string Key, Windows.Storage.ApplicationDataContainer storageSettings)
          {
              T ObjToLoad = default(T);
      
              if (storageSettings.Values.ContainsKey(Key))
              {
                  using (StringReader sr = new StringReader((string)storageSettings.Values[Key]))
                  {
                      XmlSerializer serializer = new XmlSerializer(typeof(T));
                      ObjToLoad = (T)serializer.Deserialize(sr);
                  }
              }
      
              return ObjToLoad;
          }
      
          public static void SaveSettingToStorage(string Key, object Setting, Windows.Storage.ApplicationDataContainer storageSettings)
          {
              StringBuilder sb = new StringBuilder();
              using (StringWriter sw = new StringWriter(sb))
              {
                  XmlSerializer ser = new XmlSerializer(Setting.GetType());
                  ser.Serialize(sw, Setting);
              }
      
              if (!storageSettings.Values.ContainsKey(Key))
              {
                  storageSettings.Values.Add(Key, sb.ToString());
              }
              else
              {
                  storageSettings.Values[Key] = sb.ToString();
              }
      
          }
      
          public static bool IsSettingPersisted(string Key, Windows.Storage.ApplicationDataContainer storageSettings)
          {
              return storageSettings.Values.ContainsKey(Key);
          }
      }
      
    3. Playing Sounds
    4. Silverlight MediaElement
      XNA MediaPlayerSoundEffects
      XAML MediaElement
      MonoGame   (XNA) MediaPlayerSoundEffects
      SharpDX Managed   DirectX wrappers for C#
    5. Behaviours:
    6. No built in support for behaviours (unlike WP Blend support through Interactions lib)

      http://winrtbehaviors.codeplex.com provides DragFlickBehavior

    7. Navigation:
      • Use Frame class for navigation in WinRT. Exposes methods similar to those of NaviationService.
      • Frame does not support AddBackEntry and RemoveBackEntry
      • No Back button and associated event. Add backbutton or consume a xaml page other than Basic Page (all other pages derive from LayoutAwarePage) and a back button is added and is automatically bound to correct method.
    8. NavigationService.Navigate(new Uri("/GamePlay.xaml", UriKind.Relative));
      
      if(NavigationService.CanGoBack)
          NavigationService.GoBack();
      
      Frame.Navigate(typeof(GamePlay));
      
      if(Frame.CanGoBack)
          Frame.GoBack();
      

      Designing for Windows 8

      This is the difficult part and you get the hang of this after a few AEL sessions. Windows 8 app is more than just a port of Windows Phone app.

      1)      The screen real estate is only for your apps real consumer content.

      2)      Settings Pane is a single place to hold things relating to app configuration. App config, in app purchase into, privacy policy, about etc. all these are exposed by Settings Pane.

      3)      Use Settings Flyout (Callisto lib) to link individual item to Xaml content.. e.g. settings flyout to display app config.

      4)      Windows 8 apps do more than Portrait and Landscape modes. They have snapped and filled modes as well.

      5)      There is life outside Pivot and Panorama controls. Use FlipView, Grid, GridView, Semantic zoom etc so expose your content in the best way possible.

      6)      Take your time. Porting the 1st app is always difficult – it gets a lot easier going forward.

Consume Callisto’s SettingsFlyout for #Win8Dev

With Windows 8, all Metro-style apps are supposed to publish a few things under Settings Charm. These include
1) About info
2) Privacy Policy (if you use data connection this is a must)
3) User configurable options
4) Help etc

This can be easily done using Tim Heuer’s Callisto lib for Windows 8. It ships with a handy control called SettingsFlyout. Let’s get started. I tend to register info into SettingsCharm at the start of the app and leave it at that. Lets open MainPage.xaml.cs and add to the constructor

public MainPage()
{
    // constructor
    this.InitializeComponent();

    SettingsPane.GetForCurrentView().CommandsRequested += MainPage_CommandsRequested;
}

private void MainPage_CommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
{
    SettingsCommand command = new SettingsCommand("GameRules", "Rules", (x) =>
    {
        SettingsFlyout settings = new SettingsFlyout();
        settings.Content = new GameRules();
        settings.HeaderBrush = new SolidColorBrush(Color.FromArgb(255, 0, 77, 96));
        settings.Background = new SolidColorBrush(Colors.White);
        settings.HeaderText = "Rules";
        settings.IsOpen = true;
    });

    args.Request.ApplicationCommands.Add(command);

    // and so on.. add the other commands you need to show
}

now when you app runs, you can see it in settings charm as shown

if you click the appropriate link (e.g. rules which we added), we will see

now I prefer to also show appbar icon and possible a keyboard shortcut. If we have already set both in place, lets see how we can show Rules directly from appbar, you just call ShowHelp

private void ShowHelp()
{
    SettingsFlyout settings = new SettingsFlyout();
    settings.Content = new GameRules();
    settings.HeaderBrush = new SolidColorBrush(Color.FromArgb(255, 0, 77, 96));
    settings.Background = new SolidColorBrush(Colors.White);
    settings.HeaderText = "Rules";
    settings.IsOpen = true;
}

and this is what it does.