davidpoll.com
Archive for November, 2009
Opening up Silverlight 4 Navigation: Introduction to INavigationContentLoader
Posted by david.poll in Silverlight on November 30, 2009
Quick links to followup posts:
- Event-based and Error-Handling INavigationContentLoaders
- Authentication/Authorization in an INavigationContentLoader
- On-demand loading of assemblies with Silverlight Navigation – Revisited for Silverlight 4 Beta
If you haven’t noticed by now (or been following my previous blog posts), I happen to really enjoy exploring the Navigation feature in Silverlight. A while back, I posted a number of workarounds and tips for some desirable scenarios using the Navigation feature in Silverlight 3. Then… I went silent. And the reason: I’ve been waiting for an extensibility point to be opened up in Silverlight navigation. In the Silverlight 4 beta, that extensibility point has arrived as the INavigationContentLoader.
The ContentLoader extensibility point allows developers to handle the page loading process themselves, much as you would with a GenericHandler in ASP.NET. You’re given some context on what to load (in this case a target Uri), then it’s up to you as the developer to decide how to load it. Your handling of these requests can be as specialized or as generalized as you find appropriate.
On the surface, opening up this extensibility point is a rather small change, but it’s actually very powerful when used to solve general problems. In this post, I’ll build a basic INavigationContentLoader that loads pages based on class name rather than project file structure. In future posts, I hope to explore some more general (and possibly composable) ContentLoaders.
So… Tell me about this INavigationContentLoader interface.
Fundamentally, the INavigationContentLoader interface just provides a cancellable asynchronous pattern for loading content based upon a target Uri. You can set a ContentLoader on the Frame control, which will cause the NavigationService to use your ContentLoader rather than built-in one, which is publicly available as the PageResourceContentLoader.
Here’s what the interface looks like:
public interface INavigationContentLoader { IAsyncResult BeginLoad(Uri targetUri, Uri currentUri, AsyncCallback userCallback, object asyncState); void CancelLoad(IAsyncResult asyncResult); bool CanLoad(Uri targetUri, Uri currentUri); LoadResult EndLoad(IAsyncResult asyncResult); }
The basic flow of its use with the Frame control and the NavigationService in the Silverlight SDK is as follows:
- Frame/NavigationService receives a request to navigate to a Uri
- Frame/NavigationService uses its UriMapper to map the Uri it was given to a Uri for use by the content loader
- Frame/NavigationService passes the current (post-mapping) Uri to the content loader as well as the target (post-mapping) Uri to the content loader, calling BeginLoad
- Frame/NavigationService waits for a callback from the content loader. If StopLoading() was called, the Frame/NavigationService calls CancelLoad
- Upon being called back, the Frame/NavigationService calls EndLoad() on the content loader, receiving a LoadResult
- If the LoadResult contains a redirect Uri, the Frame/NavigationService begins a new load with that Uri as the target – without adding a history entry for the target Uri
- Otherwise, the Frame/NavigationService attempts to display the fully-initialized UserControl or Page in the LoadResult
Great, I guess… Can you show me how to write one?
Sure! First, let’s choose a type of ContentLoader we’d like to create. For this ContentLoader, we’ll begin to break free of the file structure-driven bonds of the existing ContentLoader provided in Silverlight 3. Instead, we’ll allow navigation to Pages based upon the type name of the Page. For example, if I have a page called “MyNamespace.MyPage”, I should be able to navigate a frame to the relative Uri “MyNamespace.MyPage” or “/MyNamespace.MyPage” rather than having to point to the XAML file for the Page.
There are two parts to writing a ContentLoader: implementing the interface and implementing IAsyncResult to store the results of your asynchronous operation. There is ample documentation for writing an IAsyncResult out there, so I’ll conveniently ignore that for now
.
So, here’s our plan:
- Implement INavigationContentLoader
- Write a helper function that extracts a type name from a Uri
- Implement CanLoad to check to see if the type specified by the targetUri can be found and has a default constructor
- Implement BeginLoad to produce an instance of the page specified by the type in targetUri, store it in an IAsyncResult, and call the consumer’s callback
- Implement EndLoad to wrap the page in a LoadResult and return it to the consumer
- Implement IAsyncResult
- Add a “Result” property to hold the constructed page
- Use the ContentLoader
- Specify the ContentLoader in XAML
- Update Hyperlinks to navigate using our new Uri scheme
Alright, let’s hop to it!
Implementing INavigationContentLoader
Let’s start by implementing the interface:
public class TypenameContentLoader : INavigationContentLoader { }
Ok – easy! Granted, it’s a little empty, but it’s a start! Now, let’s flesh it out!
To make sense of our Uri scheme, we’ll write a method to extract a Type name from a relative Uri:
private string GetTypeNameFromUri(Uri uri) { if (!uri.IsAbsoluteUri) uri = new Uri(new Uri("dummy:///", UriKind.Absolute), uri.OriginalString); return Uri.UnescapeDataString(uri.AbsolutePath.Substring(1)); }
This method is pretty straightforward. First, it turns the relative Uri into an absolute one, using a dummy protocol. Then, it uses the Path of that Uri as the Type name (minus a leading slash and after unescaping any Uri-encoded values (e.g. %20 becomes a space character, so assembly-qualified type names can be used). The reason we don’t just use the OriginalString on the uri is because the Uri may contain a query string or a fragment (e.g. “TypeName?query=string#fragment”) – in this case we only want the Path in the Uri.
Next, we’ll implement CanLoad, which is called by the Frame/NavigationService before attempting to load. Here, we’ll check to see that the type exists and has a default constructor – both of which we’ll need in order to create an instance of the page:
public bool CanLoad(Uri targetUri, Uri currentUri) { string typeName = GetTypeNameFromUri(targetUri); Type t = Type.GetType(typeName, false, true); if (t == null) return false; var defaultConstructor = t.GetConstructor(new Type[0]); if (defaultConstructor == null) return false; return true; }
By implementing CanLoad, we can now safely assume (barring any concurrency-related race condition that could arise, but doesn’t apply for the ContentLoader we’re writing in this post because it operates neither statefully nor asynchronously) that the Frame/ContentLoader will only call BeginLoad after making this check. As such, our BeginLoad can just go ahead and try to create an instance of the type specified in the targetUri. Then, it must store the instance in an IAsyncResult, invoke the userCallback, and wait for EndLoad to be called:
public IAsyncResult BeginLoad(Uri targetUri, Uri currentUri, AsyncCallback userCallback, object asyncState) { var result = new TypenameContentLoaderAsyncResult(asyncState); Type t = Type.GetType(GetTypeNameFromUri(targetUri), false, true); object instance = Activator.CreateInstance(t); result.Result = instance; userCallback(result); return result; }
Our implementation of EndLoad will extract the instance of the page from the IAsyncResult and wrap it in a LoadResult. LoadResult is a simple class we introduced to represent the result of a load operation. It currently allows for two possible outcomes from a ContentLoader: (1) return/display a Page or UserControl, (2) provide a Uri to which users should be redirected (no history entry for the original page will be created).
public LoadResult EndLoad(IAsyncResult asyncResult) { return new LoadResult(((TypenameContentLoaderAsyncResult)asyncResult).Result); }
The final method of the INavigationContentLoader interface is CancelLoad. In our case, creating an instance of the page happens synchronously, so cancellation doesn’t really have any meaning or value. Other ContentLoaders, however, might use this method to stop a download or abort a large operation:
public void CancelLoad(IAsyncResult asyncResult) { return; }
And that’s it! Our Typename-based content loader is complete! A simple implementation of IAsyncResult will allow us to compile:
internal class TypenameContentLoaderAsyncResult: IAsyncResult { public object Result { get; set; } // Other IAsyncResult members }
Consuming the ContentLoader
Consuming our new ContentLoader is as simple as setting the ContentLoader property on your Frame in XAML:
<navigation:Frame xmlns:loader="clr-namespace:TypenameContentLoader.ContentLoader" x:Name="ContentFrame" Source="/TypenameContentLoader.Views.Home"> <navigation:Frame.ContentLoader> <loader:TypenameContentLoader /> </navigation:Frame.ContentLoader> </navigation:Frame>
You’ll note that in addition to setting the ContentLoader, I’ve set the source for the Frame control to match our new Uri scheme. We must also do the same for other hyperlinks in the application:
<HyperlinkButton x:Name="Link1" Style="{StaticResource LinkStyle}" NavigateUri="/TypenameContentLoader.Views.Home" TargetName="ContentFrame" Content="home"/> <HyperlinkButton x:Name="Link2" Style="{StaticResource LinkStyle}" NavigateUri="/TypenameContentLoader.Views.About, TypenameContentLoader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" TargetName="ContentFrame" Content="about"/> <HyperlinkButton x:Name="Link3" Style="{StaticResource LinkStyle}" NavigateUri="/TypenameContentLoader.Views.ParameterizedPage?a=100&b=1000" TargetName="ContentFrame" Content="parameterized?a=100&b=1000"/>
And there you have it! The application is fully configured to use the new ContentLoader. You’ll notice that the Frame will happily pass along the complex Uris in all three of the hyperlinks above, and the loader will load them correctly. Query string values still get parsed by the navigation service, and all is well with the world
Ok, so now I can build a ContentLoader – can I actually see the code?
Yep, and I’ll do you one better! You can also try the live sample!
And, just to prove that query strings “just work”, try this link into the application with a long list of key/value pairs that get used by the page:
Feel free to play around with it and let me know what you think!
(Also note the screenshot above using Google Chrome – now a supported browser with Silverlight 4!)
Ok, so all of this is cool, but why is it useful? What’s next?
This Typename-based content loader is a neat trick to try, but its usefulness is still pretty limited. The extensibility point itself, however, is very powerful. Instead of having to come up with hacks and workarounds for things like on-demand downloading of assemblies containing pages as I did before, we can bake that logic right into a content loader! If you are an adherent of the MVVM pattern, you can use your content loader to connect your view to your model. If all you need to do is specify constructor parameters to your pages, you now have that option! If you need to pre-load data from a web service before navigating to a page, a content loader can help!
The ContentLoader extensibility point introduced in the Silverlight 4 beta really opens up Silverlight Navigation, allowing you to interject in the page loading process and enabling you to make navigation work with whatever framework or application structure you choose.
I’ve got a bunch of ideas for useful ContentLoaders that I’ll explore (and hopefully blog about) going forward. If you’ve got ideas, questions, or feedback, please let me know! I look forward to hearing from you!
Silverlight Toolkit November 2009: Activity Control –> BusyIndicator (a.k.a. Update 3: Displaying background activity in a Silverlight RIA application)
Posted by david.poll in Silverlight on November 19, 2009
Wow! What a week! PDC, the Silverlight 4 Beta, and now the November 2009 release of the Silverlight Toolkit! There’s been a ton of great news and exciting announcements, and now I can share with you that the Activity control, first blogged here, is now a part of the Silverlight Toolkit!
Awesome! What does that mean for the Activity control?
During this transition, the Activity control underwent a few changes (thanks to my colleagues working on the Toolkit – David Anson and Jeff Wilcox) to make it more generally palatable:
- The control has been renamed from “Activity” to “BusyIndicator” in order to avoid confusion with the concept of an Activity (sounds a lot like “Task”)
- Similarly, “IsActive” is now “IsBusy”, and the visual states have been renamed appropriately as well.
- AutoBind and related properties have been removed once and for all. They were a performance hog in the original versions, and they really only hit a very, very narrow scenario. Instead, bind to a property that represents your busyness.
- MinDisplayTime has gone away. If you’re looking to change the minimum display time, you can re-template the control and add a duration to the transition from visible back to hidden.
- OverlayBrush and OverlayOpacity have been replaced with a single OverlayStyle property where you can set the color/opacity of the overlay easily.
- DisplayAfter now defaults to 0.1s instead of 0.05s
Otherwise, the control is basically the same! Give it a shot!
With this transition, the BusyIndicator control truly becomes accessible to anyone who’s using the Silverlight Toolkit. You can report bugs through that project on codeplex, and we’ll make sure to keep an eye on any feedback we get from you on the control.
Great… So where can I find it?
It’s simple! Just download the November 2009 Silverlight Toolkit for either Silverlight 3 or Silverlight 4. There are a few ways to get it:
The BusyIndicatorControl can be found in the System.Windows.Controls namespace in the System.Windows.Controls.Toolkit.dll assembly in the toolkit.
And… can I see it in action?
Yep! David Anson created some awesome samples in the Toolkit Sample Browser for the BusyIndicator. I’m a big fan of his work!
I hope you all enjoy using the BusyIndicator control in your applications! Let me know what you think!
P.S. Thanks to Jeff Wilcox, who beat me to explaining this change
I’ve been super-busy with PDC, so it was good to have someone start getting the word out early. Jeff gives a great overview of what the control is meant to do and has lots of resources regarding the Silverlight Toolkit. Check out his blog!
Activity Control, BusyIndicator, Silverlight, Silverlight 3, Silverlight 4 Beta, Silverlight Toolkit
Silverlight 4 and building business applications (PDC09-CL19)
Posted by david.poll in Silverlight on November 19, 2009
Hi everyone! Wow – yesterday was a big day, with a lot of amazing announcements at PDC ‘09 – especially the announcement that the Silverlight 4 Beta was publicly available. I was very excited to be given an opportunity to give a talk at PDC this year, and it was a real treat. My talk – Building Line of Business Applications with Silverlight 4 (PDC09-CL19) – focused on the new features in Silverlight 4 that are particularly useful in business applications, especially those that are data-centric. (Please ignore the abstract given on that page for the talk – it wasn’t updated properly from a change we made to it early on!
)

The talk covered a wide array of features, but I broke things down into three conceptual categories around data:
- Data Interactivity (i.e. how do I drill down into my data to find what I’m looking for?)
- Data Entry (i.e. how do users add/edit data and what kind of feedback do you give them to minimize mistakes?)
- Data Presentation (i.e. how do I communicate data to a user, but also how do I communicate intent for data entry, such as “choose from this list of options” to a user?)
The Silverlight 4 features I covered generally fit into these categories:
- Data Interactivity
- Data sources window (VS2010)
- Selector support (i.e. SelectedValue/SelectedValuePath on ComboBox and related controls)
- Binding TargetNullValue
- Binding FallbackValue
- ICommand support on ButtonBase (i.e. Command and CommandParameter) and Hyperlink
- Data Entry
- Asynchronous validation
- Cross-field validation
- Data Presentation
- Binding StringFormat
- CollectionViewSource Grouping
- Printing and pagination
- DataGrid * Columns (*-based column sizing, as with the Grid control)
And all of this is just the short list of features I could cover in my 50-minute talk! There are certainly other business application-friendly features out there, but more importantly, the feature list for Silverlight 4 is just huge! The talk also used Visual Studio 2010 Beta 2, which provides an awesome development environment for Silverlight.
I won’t go into too much detail here, but I wanted to share out my powerpoint deck and sample/demo code so that those who were in attendance at the talk can look back for reference, and those that weren’t can see what they were missing. I don’t know for sure yet, but I think there will be a webcast of the talk online at some point, and I’ll be happy to link to that once it’s available.
So, without further ado, here are the links:
- PDC ‘09 PPT deck
- Issue tracker demo application (source)
Before I leave you, I’d like to just give a brief overview of the sample application. The application itself is an issue tracker – allowing you to file bugs/issues, assign them to people, resolve the bugs, etc. It has 4 functional pages:
- New Issue
- Allows users to file a new bug/issue
- All Issues
- Allows users to see a list of all bugs in the database
- My Issues
- Allows users to see un-fixed issues that are assigned to them
- Reports
- Allows users to see a report of all of the issues in the database and print them if he/she so desires
The application was built using LINQ-to-SQL and WCF RIA Services (formerly .NET RIA Services), which made getting off the ground with real data running on a real database extremely quick and easy. If you’re still around at PDC, there are a few talks later today on RIA Services by Brad Abrams and Dinesh Kulkarni you should check out.
A few things to try in the application (some of which I didn’t go over in the talk):
- Right-click and change the theme of the application
- Many thanks to my co-worker Jesse Bishop for his ContextMenu control
- This feature uses implicit styles (new in SL4) to change the entire look of the application
- Set the priority on a bug to be lower than (i.e. a larger number than) severity and see the validation UI (cross-field validation)
- Set the title of an issue to be something wholly contained in another issue’s title to see the validation UI (asynchronously querying the server for “similar” bugs)
- Drag and drop a file from your disk into the list of files on a bug (one of the tabs at the bottom)
- Print out a set of reports on the reports page (click the “Print” button)
- Set a value in the “Tags” field and then change it in the DataGrid under the Attributes tab on a bug, noticing that they stay in sync (thanks to bindings to string indexers)
- Use the mouse-wheel almost anywhere and note that it works without any code to make it happen!
- Explore the code! I know there are some bugs in the application and in our beta product, but the hope is to give you an idea of how you can use these features in a business application. I’m sure there will be lots of content out there about all of these features – but this should help introduce you to them!
Well, thanks again everyone who was able to join me for my talk, and to all those who’ve been following me on twitter through this exciting announcement. Let me know if you have questions or if there’s anything you’d like me to expand on, and I’ll be more than happy to chime in!
Links to materials repeated here for convenience:
- PDC ‘09 PPT deck
- Issue tracker demo application (source)
Update (11/19/2009): Video of the talk is now available here: http://microsoftpdc.com/Sessions/CL19
Update (11/20/2009): Video of the talk is embedded below:
P.S. Sorry for the lack of posts recently – I’ve got a bunch of new topics lined up, but it was a pity not to be able to write about Silverlight 4 before it was announced. Expect another series on Navigation coming soon!
Update (12/21/2009): I think I’ve figured out the issue people were having with the downloaded project.
If you’re receiving an error like this when you try to build my project:
This is happening because Windows protects you from downloaded files by default (VS2010 will warn you when you open the project that they come from “untrusted sources.” Fixing this is pretty straightforward.
- Download the zip.
- Right-click the downloaded zip file and choose “Properties”
- At the bottom of the “General” tab, there is a “Security” section, saying “This file came from another computer and might be blocked to help protect this computer.” Click the “Unblock” button.
- Unzip and open the solution.
- Build and run!
Sorry it took me so long to figure this one out! It had me stumped for a while.
.NET RIA Services, BusyIndicator, CollectionView, Data Binding, PDC, PDC09, Silverlight, Silverlight 4 Beta, Validation, Visual Studio 2010, WCF RIA Services
-
You are currently browsing the archives for November, 2009
Recent Posts
- Pitch Perfect for Android now available
- Tag Master for Android now available
- Pitch Perfect now available for free!
- Quickly building a trial mode for a Windows Phone application
- To XAML, with love (an experiment with XAML Serialization in Silverlight)
- Taking Microsoft Silverlight 4 Applications Beyond the Browser (TechEd WEB313)
- Common Navigation UI and Authorization-driven Sitemaps
- Samples updated and code in comments
Tags
.NET RIA Services Activity Control Android Authorization Barbershop Blend BusyIndicator CollectionView ContentLoader Controls Data Binding Dynamic Navigation Fun Konami Code logging MIX '10 Navigation Off-Topic Out-of-browser PDC PDC09 Personal Pitch Perfect Printing Projects Relative Links Server Silverlight Silverlight 3 Silverlight 3 Beta Silverlight 4 Silverlight 4 Beta Silverlight 4 RC Silverlight and Beyond (SLaB) Silverlight Toolkit Sitemap Tag Master TechEd TechEd North America 2010 Trusted Applications Validation Visual Studio 2010 WCF RIA Services Windows Phone 7 XAMLTwitter: @depoll
- What a great first week at the new job! It's great to feel so energized by work.February 4, 2012 7:08
- @andruwang Amen.February 3, 2012 7:50
- @andruwang @ParseIt Likewise -- it's been a fantastic first week!February 3, 2012 6:49
Disclaimer
The content on this site represents my own personal opinions and thoughts at the time of posting, and does not reflect those of my employer in any way.
Warning: Missing argument 2 for tweetable_write_widget() in /home3/depollco/public_html/davidpoll/wp-content/plugins/tweetable/tweetable.php on line 137

