Nico's digital footprint

I grew up in the nineties, that makes me awesome by default

Navigating pages in WP8 like in Win8

by Nico

Currently, there are quite some inconsistencies between the Windows Phone SDK and the Windows 8 SDK. One of the very first that you’ll run into when developing for both platforms is the navigation api. The navigation api is used for navigating between different pages inside your app. It contains a method to navigate to a certain page, a method to navigate back one page, a few properties and so on. The thing that you’ll probably use most is the Navigate method and here’s quite a big difference between both platforms. For example, this is how you navigate to a page in Windows Phone

Code Snippet
  1. NavigationService.Navigate(new Uri("/SecondPage.xaml", UriKind.Relative));

And this is the same but in Windows 8

Code Snippet
  1. NavigationService.Navigate(typeof (SecondPage));

The Windows 8 way of navigating has one big advantage, intellisense. By navigating to a type instead of a Uri we eliminate the chance for typos or that we keep forgetting the first “/” in the Uri, or forgetting to mark it as Relative. All things I believe we’ve run into at least once before.

The service

Let’s build our own NavigationService for Windows Phone that supports navigating to a type, just like in Windows 8.

One important thing to remember when using this class is that the namespace of the page you want to navigate to has to be the same as the folder structure where your page lives in. For example, if you have a SecondPage.xaml that sits in a Views folder then the namespace should be MyApp.Views and the complete class name is MyApps.Views.SecondPage

First some properties

Code Snippet
  1. private PhoneApplicationFrame _rootFrame;
  2.  
  3. public bool CanGoBack { get { return _rootFrame.CanGoBack; } }
  4. public bool CanGoForward { get { return _rootFrame.CanGoForward; } }
  5.  
  6. public object RootFrame
  7. {
  8.     get { return _rootFrame; }
  9.     set
  10.     {
  11.         _rootFrame = (PhoneApplicationFrame)value;
  12.     }
  13. }

Our NavigationService needs a reference to the application’s RootFrame, the NavigationService in my case implements an interface that lives in a PCL. That PCL has no idea what PhoneApplicationFrame is so I made the property an object, the reason for the interface is that I might want to build this exact same service for other platforms.

CanGoBack and CanGoForward are read-only properties that just pass the values from the rootframe properties.

Next we’ll have a look at the most important function, navigating to another page.

Code Snippet
  1. public bool Navigate(Type destination)
  2. {
  3.     try
  4.     {
  5.         string fqname = destination.FullName;
  6.         var path = Regex.Split(fqname, @"\.");
  7.  
  8.         string destinationUri = string.Empty;
  9.  
  10.         for (int i = 1; i < path.Length; i++)
  11.         {
  12.             destinationUri = destinationUri + "/" + path[i];
  13.         }
  14.  
  15.         _rootFrame.Navigate(new Uri(destinationUri + ".xaml", UriKind.Relative));
  16.  
  17.         return true;
  18.     }
  19.     catch (Exception)
  20.     {
  21.         return false;
  22.     }
  23. }

The method takes in a Type, that type will be the page we want to reach. First thing we do is getting the full name of the type (namespace + class name), once we have that we can split the full name at each dot using a very simple Regular Expression. The first part of the namespace will be the app name, that’s something we don’t need so the for loop starts at the second item (index 1). The for loop will start building a string, the result will be something like “/Views/SecondPage.xaml”. Once we have that string we can navigate as usual by calling the Navigate function on the rootframe and passing in the Uri. Quite simple, and very effective. Other things I did was mapping some functions of the rootframe into my service like GoForward, GoBack, RemoveBackEntry and ResetBackStack. I’ve also created some overloads so that the service can still navigate the good old way by passing in either a string or a Uri.

Using the service

Using the service is pretty straightforward. You’ll need an instance of it in your app, one that’s available throughout the entire app. So either use an IOC or create a static property in your App.xaml.cs, in this example we’ll go with the App.xaml.cs way, just to keep it short.

In App.xaml.cs add this

Code Snippet
  1. public static NavigationService NavigationService { get; set; }

Then look for the InitializePhoneApplication method in App.xaml.cs (the one that says “Don’t add any additional code to this method”) and add some code to it Glimlach (lines 18 & 19)

Code Snippet
  1. // Do not add any additional code to this method
  2. private void InitializePhoneApplication()
  3. {
  4.     if (phoneApplicationInitialized)
  5.         return;
  6.  
  7.     // Create the frame but don't set it as RootVisual yet; this allows the splash
  8.     // screen to remain active until the application is ready to render.
  9.     RootFrame = new PhoneApplicationFrame();
  10.     RootFrame.Navigated += CompleteInitializePhoneApplication;
  11.  
  12.     // Handle navigation failures
  13.     RootFrame.NavigationFailed += RootFrame_NavigationFailed;
  14.  
  15.     // Handle reset requests for clearing the backstack
  16.     RootFrame.Navigated += CheckForResetNavigation;
  17.  
  18.     NavigationService = new NavigationService();
  19.     NavigationService.RootFrame = RootFrame;
  20.  
  21.     // Ensure we don't initialize again
  22.     phoneApplicationInitialized = true;
  23. }

Line 18 instantiates the service and line 19 sets the rootframe property, these two lines of code are the most important ones in the app.

Add some page to the app, make sure that the namespace is correct, add a button on the first page and set this as code for the button.

Code Snippet
  1. private void Button_Click(object sender, RoutedEventArgs e)
  2. {
  3.     App.NavigationService.Navigate(typeof (SecondPage));
  4. }

This will call the Navigate function on the static property in App.xaml.cs, pass in the type of the page and our NavigationService will do the rest.

Conclusion

In this post I’ve shown you a way to mimic the Windows 8 way of navigating between pages. Using this can make it easier to share code between platforms.

There are only two differences between this method and the native Windows 8 implementation.

  • We need to do some plumbing in App.xaml.cs to make the service work
  • We can’t pass parameters into the navigation, but 1) that  should be doable and 2) you shouldn’t do that. Use some messaging mechanism to send data between views / viewmodels

To end this, here’s the complete class and interface that I use regularly in my projects

Interface (lives in a PCL project)

Code Snippet
  1. /// <summary>
  2. /// Allows page navigation in the app, RootFrame needs to be set in App.xaml
  3. /// </summary>
  4. public interface INavigationService
  5. {
  6.     /// <summary>
  7.     /// The rootframe for the app, this will take care of all the navigation
  8.     /// </summary>
  9.     object RootFrame { get; set; }
  10.  
  11.     /// <summary>
  12.     /// true when there's a page on the backstack
  13.     /// </summary>
  14.     bool CanGoBack { get; }
  15.  
  16.     /// <summary>
  17.     /// true when there's a page on the forwardstack
  18.     /// </summary>
  19.     bool CanGoForward { get; }
  20.  
  21.     /// <summary>
  22.     /// go one step back on the backstack
  23.     /// </summary>
  24.     void GoBack();
  25.  
  26.     /// <summary>
  27.     /// go one step forward on the stack
  28.     /// </summary>
  29.     void GoForward();
  30.  
  31.     /// <summary>
  32.     /// resets the entire backstack
  33.     /// </summary>
  34.     void ResetBackstack();
  35.  
  36.     /// <summary>
  37.     /// remove the last entry from the backstack
  38.     /// </summary>
  39.     void RemoveBackEntry();
  40.  
  41.     /// <summary>
  42.     /// navigate to a page using the type of the page
  43.     /// </summary>
  44.     /// <param name="destination">the type of the page we want to navigate to</param>
  45.     /// <param name="parameter">an optional parameter</param>
  46.     /// <returns>true/false</returns>
  47.     bool Navigate(Type destination);
  48.  
  49.     /// <summary>
  50.     /// navigate to a page using a uri string, paramers are passed using querystring
  51.     /// </summary>
  52.     /// <param name="uri">string pointing to the page we want to navigate too</param>
  53.     /// <returns></returns>
  54.     bool Navigate(string uri);
  55.  
  56.     /// <summary>
  57.     /// navigate to a page using a uri, paramers are passed using querystring
  58.     /// </summary>
  59.     /// <param name="uri">uri we want to navigate too</param>
  60.     /// <returns></returns>
  61.     bool Navigate(Uri uri);
  62. }

Implementation in a Windows Phone project

Code Snippet
  1. public class NavigationService : INavigationService
  2. {
  3.     private PhoneApplicationFrame _rootFrame;
  4.  
  5.     public bool CanGoBack { get { return _rootFrame.CanGoBack; } }
  6.     public bool CanGoForward { get { return _rootFrame.CanGoForward; } }
  7.  
  8.     public object RootFrame
  9.     {
  10.         get { return _rootFrame; }
  11.         set
  12.         {
  13.             _rootFrame = (PhoneApplicationFrame)value;
  14.         }
  15.     }
  16.  
  17.     public void GoBack()
  18.     {
  19.         if (!_rootFrame.CanGoBack) return;
  20.  
  21.         _rootFrame.GoBack();
  22.     }
  23.  
  24.     public void ResetBackstack()
  25.     {
  26.         _rootFrame.BackStack.GetEnumerator().Reset();
  27.     }
  28.  
  29.     public void RemoveBackEntry()
  30.     {
  31.         _rootFrame.RemoveBackEntry();            
  32.     }
  33.  
  34.     public void GoForward()
  35.     {
  36.         if (!_rootFrame.CanGoForward) return;
  37.  
  38.         _rootFrame.GoForward();
  39.     }
  40.  
  41.     public bool Navigate(Type destination)
  42.     {
  43.         try
  44.         {
  45.             string fqname = destination.FullName;
  46.             var path = Regex.Split(fqname, @"\.");
  47.  
  48.             string destinationUri = string.Empty;
  49.  
  50.             for (int i = 1; i < path.Length; i++)
  51.             {
  52.                 destinationUri = destinationUri + "/" + path[i];
  53.             }
  54.  
  55.             _rootFrame.Navigate(new Uri(destinationUri + ".xaml", UriKind.Relative));
  56.  
  57.             return true;
  58.         }
  59.         catch (Exception)
  60.         {
  61.             return false;
  62.         }
  63.     }
  64.  
  65.     public bool Navigate(string uri)
  66.     {
  67.         try
  68.         {
  69.             _rootFrame.Navigate(new Uri(uri, UriKind.Relative));
  70.  
  71.             return true;
  72.         }
  73.         catch (Exception)
  74.         {
  75.             return false;
  76.         }
  77.     }
  78.  
  79.     public bool Navigate(Uri uri)
  80.     {
  81.         try
  82.         {
  83.             _rootFrame.Navigate(uri);
  84.  
  85.             return true;
  86.         }
  87.         catch (Exception)
  88.         {
  89.             return false;
  90.         }
  91.     }
  92. }

Enjoy!


Tags:

.Net | WP8 | PCL | XAML

Traffic Chat: My new Windows Phone 8 app

by Nico

I launched a new Windows Phone 8 app last week called Traffic Chat. A friend of mine came up what the idea of having a chat with other drivers that are stuck in the same traffic jam as you are, perfect idea for a smartphone app.

The way the app works is actually fairly easy, the app detects the street that you’re on, takes your license plate (the plate is saved into the Isolated Storage Settings so it only needs to be entered on first start). The apps sends that data to the server (powered by SignalR and running on Azure Websites), the server checks if a chatroom with the name of the street already exists, if it doesn’t it creates it first, and then enters you as a user, with your license plate as username, into the chatroom.

The great thing about the app is that it hardly requires any user interaction to get started. Since you’re still behind the weel of a car this was very important to me, safety first. Once the app launches it starts detecting immediately with a big pulsating icon to show that it’s still working, if something goes wrong the icon turns red and a big retry button appears.

Even the chatting can be done hands free through speech-to-text.

And as usual, once the app was released I noticed a small mistake on my part, once you’re chatting there’s a button to let your social networks know that you’re using the app but the link that should point to the app actually points to MSDN, oops. An update for this is submitted and should be live this week.

So, try out the app whenever you’re stuck in traffic, but do be careful. Any features missing? Or have some cool idea? Get in touch and I’ll see what I can do, props will be given where needed of course Glimlach

Download the app


Tags:

Making Resharper and MVVM Light’s ViewModelBase play nice

by Nico

ReSharper and MVVM Light are probably my two most used pieces of software. I can’t live without Resharper’s refactoring skills and doing any kind of XAML development without using MVVM Light is just crazy (my opinion of course Glimlach).

One of the more annoying things in XAML based software is the need to write full properties that call the PropertyChanged event in the setter. If your project is data intensive you’ll probably need a lot of those properties, luckily Resharper can help us there.

The Resharper solution

When you make your class implement INotifyPropertyChanged it requires you to implement its members, Resharper comes with a built-in implementation, just press alt-enter and behold.

After inserting the code Resharper asks if you want to include some annotations in your project, and these annotations make some magic happen, so I would strongly advice to add them.

Once you click Yes you’ll notice that a new class is added to your project under the Properties folder. The INotifyPropertyChanged implementation looks like this

Code Snippet
  1. public class MyBase : INotifyPropertyChanged
  2. {
  3.     public event PropertyChangedEventHandler PropertyChanged;
  4.  
  5.     [NotifyPropertyChangedInvocator]
  6.     protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
  7.     {
  8.         PropertyChangedEventHandler handler = PropertyChanged;
  9.         if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
  10.     }
  11. }

As you can see Resharpes uses the CallerMemberName attribute new in .net 4.5, this way we won’t have to specify the property’s name anymore when we call OnPropertyChanged. Line 5 is what will make the next piece of Resharper magic happen.

Now we want to add some properties to the class and make them call OnPropertyChanged in the setter. I start of with an autoproperty

Code Snippet
  1. public string Name { get; set; }

Next I alt-enter the property. Resharper now checks the class and its baseclasses if available, if one of those has the NotifyPropertyChangedInvocator attribute it will show an extra option in the menu.

Selecting that option will turn the autoproperty into

Code Snippet
  1. private string _name;
  2. public string Name
  3. {
  4.     get { return _name; }
  5.     set
  6.     {
  7.         if (value == _name) return;
  8.         _name = value;
  9.         OnPropertyChanged();
  10.     }
  11. }

Mission accomplished, we create a bunch of autoproperties, alt-enter them and save a lot of time.

The MVVM Light problem

The MVVM Light viewmodels all inherit from ViewModelBase, ViewModelBase inherits from ObservableObject and ObservableObject implements INotifyPropertyChanged

Code Snippet
  1. public abstract class ViewModelBase : ObservableObject, ICleanup

 

Code Snippet
  1. public class ObservableObject : INotifyPropertyChanged

And here’s the MVVM Light implementation of INotifyPropertyChanged

Code Snippet
  1. public event PropertyChangedEventHandler PropertyChanged;
  2.  
  3. protected virtual void RaisePropertyChanged(string propertyName)
  4. {
  5.     VerifyPropertyName(propertyName);
  6.  
  7.     var handler = PropertyChanged;
  8.     if (handler != null)
  9.     {
  10.         handler(this, new PropertyChangedEventArgs(propertyName));
  11.     }
  12. }
  13.  
  14. public void VerifyPropertyName(string propertyName)
  15. {
  16.     var myType = GetType();
  17.  
  18.     if (!string.IsNullOrEmpty(propertyName)
  19.         && myType.GetProperty(propertyName) == null)
  20.     {
  21.         throw new ArgumentException("Property not found", propertyName);
  22.     }
  23. }

A nice implementation but it lacks the attributes required for Resharper to implement a backing field with change notification. Meaning that we still have to write the implementation ourselves or we need to build our own ViewModelBase and implement INotifyPropertyChanged our self, which is a bit of a shame since this nice implementation already exists.

A solution

The solution I came up with does require us to build a viewmodelbase, but to be honest I tend to do that in almost every project, for example for an IsDataLoading bindable property, that’s useful in every page. The ViewModel base class that we’ll build inherits from ViewModelBase and overrides the RaisePropertyChanged. Do make sure that the annotations.cs class from Resharper is present in your project.

Code Snippet
  1. public class MyBase : ViewModelBase
  2. {
  3.      /// <summary>
  4.     /// This gives us the ReSharper option to transform an autoproperty into a property with change notification
  5.     /// Also leverages .net 4.5 callermembername attribute
  6.     /// </summary>
  7.     /// <param name="property">name of the property</param>
  8.     [NotifyPropertyChangedInvocator]
  9.  
  10.     protected override void RaisePropertyChanged([CallerMemberName]string property = "")
  11.     {
  12.         base.RaisePropertyChanged(property);
  13.     }
  14. }

The overriden method just calls its base method and passes in the parameter. But thanks to .net 4.5 and the attribute we can now use the CallerMemberName attribute and Resharper’s alt-enter magic in MVVM Light while still having the ViewModelBase.

And the result of that action is like you would suspect

Code Snippet
  1. private string _name;
  2. public string Name
  3. {
  4.     get { return _name; }
  5.     set
  6.     {
  7.         if (value == _name) return;
  8.         _name = value;
  9.         RaisePropertyChanged();
  10.     }
  11. }

Conclusion

In this post I’ve shown a quick fix I use to make two of my favorite bits play together nicely without changing any of the native implementations, I still use the ViewModelBase way of notifying when a property changed and I can make use of Resharper to quickly write those properties.


Tags:

  Log in

About the author

Hi,

My name is Nico, I’m an MVP Windows Platform Development living in Belgium.
I’m currently employed as a .NET consultant at RealDolmen, one of Belgium’s leading IT single source providers.

I'm also founding member and board member of the Belgian Metro App Developer Network, a user group focussed on Windows 8 and Windows Phone development. If you're in Belgium feel free to drop by if we're doing an event. http://www.madn.be

Since June 2012 I'm a proud member of Microsoft's Extended Experts Team Belgium. And in February 2013 I became a member of DZone's Most Valuable Bloggers family.

In 2013 I became a book author and wrote "Windows 8 app projects, XAML & C# edition".

In 2014 I received the MVP award for the very first time.

I hope to get feedback from my readers either through comments, mail (nico_vermeir@hotmail.com), twitter, facebook, …

 

mvp

 

mvp

 

 

MeetLogo

 

MVBLogo

mybook

 

Month List