With all the Windows 8/Metro/WinRT hype on the internet today, I decided it was time for a quick tip concerning the XAML escape sequence and the good old navigation framework present in Silverlight 4 and Silverlight 5. I only learned about the XAML escape sequence until recently and I can image that there quite a number of people out there that are still unfamiliar with it. The nice thing is that you can also use the XAML escape sequence in WPF, Windows Phone and WinRT, if you like to do so.
The problem
When you use the navigation framework in Silverlight, you probably also want to use an UriMapper, to shield your users from the complete path of the XAML files and the .xaml extension. Such an UriMapper could look something like this:
1: <uriMapper:UriMapper>
2: <uriMapper:UriMapping Uri="Home" MappedUri="/Views/Home.xaml"/>
3: <uriMapper:UriMapping Uri="About" MappedUri="/Views/About.xaml"/>
4: </uriMapper:UriMapper>
A small bug in the navigation framework activates the browser’s back button when the user navigates to your Silverlight application for the very first time. This isn’t that bad, except for the exception when the user actually presses the back button:
A well known workaround for this problem is to change your UriMapper like this:
1: <uriMapper:UriMapper>
2: <uriMapper:UriMapping Uri="" MappedUri="/Views/Home.xaml"/>
3: <uriMapper:UriMapping Uri="Home" MappedUri="/Views/Home.xaml"/>
4: <uriMapper:UriMapping Uri="About" MappedUri="/Views/About.xaml"/>
5: </uriMapper:UriMapper>
Which causes your application to navigate when the entered uri is empty, which happens when the user presses the back button of the browser when he first visits your application. While this does fix the exception in case of an empty uri, this doesn’t fix the exception that occurs when the user manipulates the uri (after the pound sign in the browser’s address bar) directly and enters an invalid one. This is where the XAML escape sequence comes into play.
The solution
What I essentially want to do is to change the UriMapper like this:
1: <uriMapper:UriMapper>
2: <uriMapper:UriMapping Uri="" MappedUri="/Views/Home.xaml"/>
3: <uriMapper:UriMapping Uri="Home" MappedUri="/Views/Home.xaml"/>
4: <uriMapper:UriMapping Uri="About" MappedUri="/Views/About.xaml"/>
5: <uriMapper:UriMapping Uri="{invalidPage}" MappedUri="/Views/Error.xaml"/>
6: </uriMapper:UriMapper>
Notice the last UriMapping element. This should mean that whatever uri was entered, if the UriMapper doesn’t find a match it eventually redirects to an error page. If you’d try the above XAML, you would find out that this can’t be parsed. Since the XAML parser sees that the Uri attribute of the UriMapping element starts with a “{”, it thinks that it’s a binding expression and of course we don’t have an “invalidPage” binding in Silverlight. So I needed something to escape the binding expression. Turns out that XAML does have an escape sequence, it’s just not that well known, at least not by me. The XAML escape sequence are two curly braces: “{}”. Deeply buried in the XAML specification is the following sentence: “The escape sequence is not a markup extension and is not backed by a class. However, it is a convention that XAML readers (including custom XAML readers) should respect.” This means that some exotic, custom XAML parsers might not support this escape sequence, but why on earth would you want to use one of them? If I change the last UriMapping element to the following :
1: <uriMapper:UriMapping Uri="{}{invalidPage}" MappedUri="/Views/Error.xaml"/>
All works fine when an invalid uri is entered:
Concluding
While I just learned about XAML wildcards very recently, it seems to me that they are quite useful. The scenario above is just one example, I’m sure you can come up with a lot more!