Friday, February 25, 2011

Building a Windows Phone 7 Application with UltraLight.mvvm

I recently released a new open source project called simply UltraLight.mvvm. The purpose of this project is to make it easier to build MVVM-based applications that support tombstoning (a must) on Windows Phone 7. The DLL is 22KB and the source is less than 300 lines of code.

With that, the framework supports:

  • Commands
  • Command binding for buttons (with parameters)
  • Support for binding commands to application buttons on the application bar
  • Dialogs, both notification and confirmation
  • Messaging using the event aggregator publisher/subscriber model
  • Service location
  • Design-time friendly view models
  • Tombstone-friendly view models with control hooks for tombstone events
  • Decoupled navigation support from the view model
  • Decoupled visual state support from the view model
  • Notify property changed using expressions instead of magic strings
  • Dispatcher helper for UI thread access

Why not Jounce?

I think Jounce is overkill for the phone. Jounce specifically and explicitly relies on the Managed Extensibility Framework which is a phenomenal tool for building modular line of business applications for Silverlight. While the phone is Silverlight, and while there are certainly business applications on the phone, there are several reasons why I think it requires a completely different framework. These include:

  • The importance of the back button behavior that creates a very tight coupling to the navigation framework that is built-in
  • The fact that the applications are never launched from the web, but always executed as a first-class application on the phone
  • The limited resources available on the phone
  • The lack of certain key features that MEF leverages such as Reflection.Emit on the phone
  • The unique requirements created by tombstoning

For this reason, I wanted something quick and easy that would get me 90% of the way without much fuss. That's what this framework is.

I created a sample application to demonstrate the use of the framework. The application is bundled with the source and of this writing there is not a formal release, only the source with two projects: the framework itself and a sample phone application. You can download this from the CodePlex site.

Ultra Light MVVM Framework for Windows Phone 7

Getting Started: View Models

The first step is the view model. Some people won't like this but I created an interface with the "base" properties for the view model that I can use for my design, and then another interface that includes the framework's IViewModel to apply to the runtime. Why won't everybody like this? Because it really ends up being an empty interface that intersects two other interfaces. However, it makes it easier to build my design view model without having to stub out properties in the base view model that the designer doesn't need. Here are the interfaces:

public interface IMainBase
{
    string Text { get; }

    IActionCommand<object> EventCommand { get; }

    IActionCommand<object> StateCommand { get; }

    IActionCommand<object> DialogCommand { get; }

    IActionCommand<object> NavigateCommand { get; }
}

public interface IMainViewModel : IMainBase, IViewModel
{
        
}

With that, I can create a design-time view model with stubbed out properties:

public class DesignMainViewModel : IMainBase 
{         
    public string Text
    {
        get { return "This is some design-time text."; }
    }

    public IActionCommand<object> EventCommand { get; set; }

    public IActionCommand<object> StateCommand { get; set; }
        
    public IActionCommand<object> DialogCommand { get; set; }

    public IActionCommand<object> NavigateCommand { get; set; }        
}

In this case I really only had to mock one thing, the text field. In the XAML for the main page, I can then reference the design view model using the design-time extensions like this:

<Grid d:DataContext="{d:DesignInstance design:DesignMainViewModel, IsDesignTimeCreatable=True}"/>

This will show up nicely in the designer. The rest of the layout is simple. I wrap a border and add some visual states to make the border red or yellow to show how the framework works with the Visual State Manager. I have a text box for you to enter text and show it bound both in the text box and in a text block. I have a button to change states, to send the text via the event aggregator, and to navigate to another page. Finally, there is an application button that allows you to "delete" (clear) the text after answering a dialog.

You can see the button/command binding in the button that changes the visual state - notice it passes the target state as a parameter:

<Button Grid.Row="4" Content="Red Border" 
        MVVM:ButtonCommand.Command="{Binding StateCommand}"
        MVVM:ButtonCommand.CommandParameter="RedBorder"
        HorizontalAlignment="Center"/>

ActionCommand and Changing States

Let's take a look at the view model and how this is implemented with the ActionCommand provided by the framework. The command to change the state is valid if a non-empty string is passed. The base class is wired to the visual state manager, so the view model can simply call the GoToVisualState method. The command is wired like this:

StateCommand = new ActionCommand<object>(
    s =>
        {
            GoToVisualState(s.ToString(), true);
            _lastViewState = s.ToString();
        },
    s=>s is string && !string.IsNullOrEmpty((string)s));

That's it - you can databind the command parameter, or, like I did, pass in a literal. When you click the button, the state is changed and you can see the transitions as it fades from one color to the next. I save the state for tombstoning - more on that later.

Binding the View Model

Of course, for that to work, the view model has to get bound. I don't mind a little code-behind to get the job done if it's straightforward and easy. First, in my application start up, I need to register the view model. I'm telling the framework to handle exactly one copy of my view model and give it back whenever I ask for it (if you want new ones, you can just create new ones - no problem there). When the application starts, I call a simple method that registers the view model:

private static void _RegisterViewModels()
{
    UltraLightLocator.Register<IMainViewModel>(new MainViewModel());
}

Now it is set up to return that instance anytime I ask for it.

The framework provides an extension method to binding the view model to the view. I decided to go with a method that would take a framework element. Some people won't like this, but I have a good reason. The binding can affect how the datacontext is propagated through the hierarchy, and some controls used as the "root" control can behave differently when they are bound too soon. By allowing the element to be passed, you have more control over where in the visual tree it is bound and how. Most often, you'll do what the example does and simply bind it to the root grid, often called LayoutRoot. Here is the code-behind for the main page:

public MainPage()
{
    InitializeComponent();
    this.BindToViewModel<IMainViewModel>(LayoutRoot);
}

That's it - I just pass the contract for the view model and the element to bind to. Behind the scenes, the framework will attach to the loaded event of that element and wait to actually data-bind until it is fully loaded. If you are working with a control like the pivot control, which will throw errors if you bind to it too soon, this will avoid that problem. It will also set up a delegate to call into the Visual State Manager, and wire in the navigation context so the view model can raise navigation events. When you bind to a user control, it will walk the visual tree to find the host page in order to grab a valid navigation context.

Navigation

That takes us to navigation. The navigation button fires a navigation command. The command is wired to call a method, and the method looks like this:

private void _Navigate()
{
    RequestNavigation("/SecondPage.xaml");
}

Just request navigation and pass the view. The framework handles casting this to a URI and then passing it to the navigation context. You can also call GoBack() to cancel or go to a previous page.

The Event Aggregator

I used the same code for the event aggregator that I use in Jounce as it is lightweight and robust. The command to send the event is wired to publish whatever text has been entered. It is set up like this:

EventCommand = new ActionCommand<object>(
    o => UltraLightLocator.EventAggregator.Publish(Text),
    o=>!string.IsNullOrEmpty(Text));

Notice how easy it is to send a message - just grab the instance for the aggregator and publish it. It can be any type. To receive a message, you simply implement IEventSink<T> where T is the type of message you want to listen for. In this case, the same view model also listens for its own message (hey, this is a demo, right?) You can see in the definition the IEventSink<string> which requires you to create a method that is called with the message.

To subscribe, you pass an instance of the class that has implemented the interface. Because this is set up for only one message, the type doesn't have to be specified as it can be inferred from the interface:

UltraLightLocator.EventAggregator.SubscribeOnDispatcher(this);

Notice you have the option to subscribe directly, or if you know you'll be interacting with the UI thread you can subscribe on the dispatcher and the method will be called from the UI thread. If you implement multple interfaces, you just indicate the type of message you are subscribing for like this:

UltraLightLocator.EventAggregator.SubscribeOnDispatcher<string>(this);

Dialogs

I created a simple interface to abstract the dialog mechanism. It takes a title, a message, and a boolean to determine if it is a notification (you can only click OK) or a confirmation (OK or Cancel). When the message is received, a notification is sent in the receiving method:

public void HandleEvent(string publishedEvent)
{
    Dialog.ShowMessage("Received Text", publishedEvent, false);
}

Application Button Binding

One aspect of the phone I don't like is the fact that the application buttons are not directly bindable. There are some interesting solutions there but I decided to just make it simple: if you specify three buttons, return an array of three commands that map to the buttons. In this case, we have a "delete" button that clears the text field. It only makes sense to call it if there is text, so the command is set up like this:

DialogCommand = new ActionCommand<object>(
    o => _RequestDelete(),
    o => !string.IsNullOrEmpty(Text));

The delete request uses the dialog as well, this time to confirm the request:

private void _RequestDelete()
{
    if (Dialog.ShowMessage("Confirm Delete","Click OK to Clear the Text.", true))
    {
        Text = string.Empty;
    }
}

Finally, the command is bound to the button by returning it in the button bar list:

public override IEnumerable<IActionCommand<object>> ApplicationBindings
{
    get { return new[] { DialogCommand }; }
}

If you have nothing to bind, you can just return an empty list.

Tombstoning

The final element to cover is tombstoning support. The interface ITombstoneFriendly is provided to indicate the view model will explicitly support tombstoning. The pattern for tombstoning can be simplified to this:

  1. When tombstoned, save data
  2. When activated, load data
  3. When the application exits, clear the saved data so the application "starts fresh"

The tombstone interface provides two methods to save and then restore data. In the example, the text is saved, as well as the last view state. If you make the border red and tombstone, it will still be red when you return to the application. (Hint: using Sterling makes this a whole lot easier).

Here is the implementation of the interface for the sample application:

public void Deactivate()
{
    var settings = IsolatedStorageSettings.ApplicationSettings;
    settings["ViewState"] = _lastViewState;
    settings["Text"] = Text;
}

public void Activate()
{
    var settings = IsolatedStorageSettings.ApplicationSettings;
    if (settings.Contains("ViewState"))
    {
        _lastViewState = (string) settings["ViewState"];
        GoToVisualState(_lastViewState, false);
    }
    if (settings.Contains("Text"))
    {
        Text = (string) settings["Text"];
    }
}

Also, in the application object, when the application exits normally, I clear the settings:

private void Application_Closing(object sender, ClosingEventArgs e)
{
    var settings = IsolatedStorageSettings.ApplicationSettings;
    if (settings.Contains("ViewState"))
    {
        settings.Remove("ViewState");
    }            
    if (settings.Contains("Text"))
    {
        settings.Remove("Text");
    }
}

There is a special process to bind the view to the view model for the tombstone process. The code-behind for the main page adds two overrides that look like this:

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
    this.DeactivatePage<IMainViewModel>();
    base.OnNavigatedFrom(e);
}

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    LayoutRoot.ActivatePage<IMainViewModel>();
    base.OnNavigatedTo(e);
}

Wiring these events causes the framework to cast the view model to ITombstoneFriendly and call the appropriate method. Notice that the deactivate command extends the page and uses this, but the activate command extends a framework element. Why is that? Once again, if you are using a pivot control or a panorama control, the navigation event happens before the control is fully loaded. Binding too soon will result in the controls throwing an exception. By extending from the element itself (i.e. if you use a pivot, you use the name of the pivot control instead of the layout root to call ActivatePage) the framework knows to wait for that element to load. Only when the element is loaded will it call the tombstone method. It will also dispatch this on the UI thread to queue it behind any pending requests, allowing for a seamless transition from the tombstoned state.

Conclusion

As you can see, it is a very small framework but does quite a bit. It's by no means a magic "pull the lever and I have a full blown Windows Phone 7" application, but I believe it is solid enough to help anyone hit the ground running and small enough that you can modify or extend it to fit your specific needs. I look forward to any feedback and suggestions.

Jeremy Likness

Jounce Part 11: Debugging MEF

The Jounce framework specifically relies on the Managed Extensibility Framework to help solve MVVM concerns. I recently presented an introduction to MEF and explained what I believe are the four core problems it solves:

  1. Discovery — it's good to decouple, but at some point you need to provide an implementation, and MEF does a great job of discovering implementations, wiring their dependencies, and providing them to you
  2. Lifetime management — instead of mangling classes to follow the singleton pattern, MEF provides you with a way to manage the lifetime of those classes through attributes. You can define whether or not an instance is shared or generated both where you define the class and when you require it, giving you plenty of flexibility over how the class is managed without having to change it
  3. Extensibility — this often throws people off because they believe it is just for plug-ins. The fact is MEF has a very easy, built-in means for dynamically loading XAP files and integrating them into your main application, making modularity and extensibility easy to implement
  4. Metadata — Jounce uses this extensively: the ability to tag an implementation with additional data and filter that data to route implementations and only create them on demand when needed. This is how Jounce manages views, view models, and regions

The one drawback to using MEF is troubleshooting. Sometimes the composition step — when MEF scans all of the requirements and contracts in a project and maps in the implementations that satisfy them — can fail and it's not immediately clear why. MEF uses stable composition, so if any part of a hierarchy fails to import the correct references, the entire composition step will fail. This is intentional so you don't get unexpected behavior when you are asking for a dependency and it can't be provided.

Fortunately, MEF provides plenty of hooks to debug what is going on when composition occurs. Jounce uses a special debug container that can actually be used independently of Jounce for your MEF projects. It is in a class called MEFDebugger and you can browse the source at CodePlex here.

The class constructor takes in a container and a logging mechanism. The logger is what messages are written to. The default logger supplied by Jounce simply emits debug statements, but it can be replaced by any implementation of your own and wired into any third-party logger available for Silverlight. The container is the main MEF container. Jounce configures this container when the application is started and passes it into the MEF debugging container. The debug container is closed — there are no additional methods or properties — so you simply maintain a reference to keep it alive for the duration of the application.

The first thing the debugger does is hook into an ExportsChanged event. This fires any time a new XAP file is loaded or the catalog is modified in any way that results in a change of exports. This is when recomposition comes into play and typically happens the first time the container is composed and subsequently whenever a dynamic XAP file is loaded.

Whenever the exports change, the debugger simply walks through the added parts, the removed parts, and the contract changes and emits those. It also examines the metadata in the exports and writes those out as well. Using the ToString override on your classes helps provide more friendly/readable information when the values of attributes or exports themselves are written out.

The call to debug the catalog simply walks through all import and export definitions and does the same thing. The end result is that you receive a stream of debug information explaining exactly what catalogs are included, what parts are found, the imports, exports, and metadata found in the parts, and any new information when recomposition occurs.

The easiest way to see this in action is to run the quick start. Set the DynamicXAPCalculatorTestPage.aspx page in the web project as the start page to launch this example. Jounce will parse the init params for the debug level to use in the logger. Add this init parameter to ensure you receive verbose debug information:

<param name="initParams" value="Jounce.LogLevel=Verbose" />

When you run the application in the debugger, you'll see very explicit container information sent to the debug window. For example, here is the part that represents the view shell. Notice it requires an import for the event aggregator, and exports a user control and a binding. You can also see the associated metadata, which in this case is the flag marking this as IsShell=true.

2/25/2011 6:44:47 AM Verbose Jounce.Core.MefDebugger :: MEF: Found part: DynamicXapCalculator.Views.Shell
2/25/2011 6:44:47 AM Verbose Jounce.Core.MefDebugger ::    With import: DynamicXapCalculator.Views.Shell.EventAggregator (ContractName="Jounce.Core.Event.IEventAggregator")
2/25/2011 6:44:47 AM Verbose Jounce.Core.MefDebugger ::    With export: DynamicXapCalculator.Views.Shell (ContractName="System.Windows.Controls.UserControl")
2/25/2011 6:44:47 AM Verbose Jounce.Core.MefDebugger ::       With key: ExportedViewType = Shell
2/25/2011 6:44:47 AM Verbose Jounce.Core.MefDebugger ::       With key: IsShell = True
2/25/2011 6:44:47 AM Verbose Jounce.Core.MefDebugger ::       With key: Category = 
2/25/2011 6:44:47 AM Verbose Jounce.Core.MefDebugger ::       With key: MenuName = 
2/25/2011 6:44:47 AM Verbose Jounce.Core.MefDebugger ::       With key: ToolTip = 
2/25/2011 6:44:47 AM Verbose Jounce.Core.MefDebugger ::       With key: ExportTypeIdentity = System.Windows.Controls.UserControl
2/25/2011 6:44:47 AM Verbose Jounce.Core.MefDebugger ::    With export: DynamicXapCalculator.Views.Shell.Binding (ContractName="Jounce.Core.ViewModel.ViewModelRoute")
2/25/2011 6:44:47 AM Verbose Jounce.Core.MefDebugger ::       With key: ExportTypeIdentity = Jounce.Core.ViewModel.ViewModelRoute

The calculator provides some basic functions for addition and subtraction. Multiplication and division are loaded in a dynamic XAP file. Click the link to load the advanced functions, and watch the debug window. You'll notice that additional exports are added to the container:

2/25/2011 6:48:16 AM Verbose Jounce.Core.MefDebugger :: Added Export: DyanmicXapCalculatorAdvanced.AdvancedFunctions.AddCommand (ContractName="System.Tuple(System.String,System.Windows.Input.ICommand)")
2/25/2011 6:48:16 AM Verbose Jounce.Core.MefDebugger ::       With key: ExportTypeIdentity = System.Tuple(System.String,System.Windows.Input.ICommand)

You'll also find that the contract for the commands that drive the calculator has changed (because it now has additional exports to use):

2/25/2011 6:48:16 AM Verbose Jounce.Core.MefDebugger :: Changed contracts:
2/25/2011 6:48:16 AM Verbose Jounce.Core.MefDebugger ::  ==>System.Tuple(System.String,System.Windows.Input.ICommand)
2/25/2011 6:48:16 AM Verbose Jounce.Core.MefDebugger ::  ==>System.ComponentModel.Composition.Contracts.ExportFactory

As you can see, a lot of detailed information is provided that most of the time will help you track down exactly where the imports, exports, and metadata that make up parts is coming from. By examining what is generated and what your code is expecting, you can quickly track down where composition errors may be coming from. With your own logger implementation you can easily route these messages to the server, a text file, or even store them in isolated storage for later inspection.

Jeremy Likness

Sunday, February 20, 2011

Codestock and Knoxville, Tennessee: Are You Coming in 2011?

Codestock is an amazing event that I first attended last year in Knoxville, Tennessee. It's hosted at a great venue in a wonderful city and loaded with exciting sessions. I had just as much fun speaking at my session as I did attending the other sessions and learning about new technologies.

I've submitted two talks this year and if you are planning on coming and are interested in these topics, please cast your vote. Codestock, unlike other venues, gives priority voting to those who have registered. If you do register, you can vote for my sessions here:

The Sterling Database for Silverlight and Windows Phone 7: The release of Silverlight 4 and Windows Phone 7 have created an explosion of line of business applications written in Silverlight. The framework provides a powerful advantage with its ability to run offline and disconnected from the network. For browser applications this provides a unique data storage challenge. Windows Phone 7 applications must also cater to the “tombstoning” scenario and efficiently serialize and rehydrate data when the program is swapped to the background and back. Sterling is an open source object-oriented database that addresses these needs by storing data in isolated storage. Sterling works with existing classes/types and is extremely lightweight. Learn how to use Sterling from its creator, Jeremy Likness, when he walks you through various scenarios and features involving indexes, LINQ to object queries, foreign keys, triggers, encryption, and compression.

Silverlight 5 for Line of Business Applications: Silverlight 5 has been announced and will provide a variety of incredible features beneficial to line of business applications. Microsoft Silverlight MVP Jeremy Likness will cover these features and teach you how to produce high performance scalable applications using the latest Silverlight framework. Learn how Postscript printing, improved MVVM support with XAML and data-binding debugging, implicit data templates, style binding, WS-Trust support, 64-bit support and more enhance the current runtime and take Silverlight to the next level within the enterprise.

I appreciate your support and hope to see you in Knoxville!

Jeremy Likness

Monday, February 14, 2011

Windows Phone 7 Tombstoning with MVVM and Sterling

Yesterday I wrote about an ultra light Windows Phone 7 MVVM Framework and mentioned that I would deal with tombstoning in a later post. This is the post.

Sterling makes tombstoning very easy because it handles serialization of just about any type of object. To show an example, we'll start with the concept of a view model that holds a set of categories (that a pivot is bound to) and a set of items that are filtered by category. When tombstoned, the application must remember the category as well as any item that is selected.

Build the Tombstone

First thing to do is create the generic tombstone model to hold values. This is the model:

public class TombstoneModel
{
    public TombstoneModel()
    {
        State = new Dictionary<string, object>();
    }

    public Dictionary<string, object> State { get; set; }

    public T TryGet<T>(string key, T defaultValue)
    {
        if (State.ContainsKey(key))
        {
            return (T)State[key];
        }
        return defaultValue;
    }
}

But wait ... what's the point? Isn't that just like the application settings object? Sure ... sort of. There are a few problems with application settings. First, they don't handle complex object graphs and the objects must be serializable. They don't recognize things like "foreign keys" or sub lists. Second, they load into memory as opposed to isolated storage files which can be loaded on demand.

Sterling, on the other hand, can handle almost any type of object (and for the ones it can't handle, you can write a custom serializer).

Define the Tombstone Table

A full lesson on Sterling is outside the scope of this post. To learn about Sterling, read the User's Guide. To define a table in Sterling, you pass the type of the table and a key. Because there will only ever be one instance of the tombstone model, you cheat the key and make it always have a "true" value like this:

CreateTableDefinition<TombstoneModel,bool>(c=>true)

Finally, because the tombstone model is only to hold values that must be saved during a tombstone event, the model should be cleared when the application truly closes (as opposed to being deactivated due to a tombstone event). Therefore, in the Application_Closing method you can delete the tombstone model, if it exists:

private void Application_Closing(object sender, ClosingEventArgs e)
{
    Database.Delete(typeof (TombstoneModel), true);
}

Now everything is set to handle the tombstone properties.

Making your View Model a Caretaker

What other way is there to describe a view model that is "tombstone friendly?" To make a view model friendly, decorate it with the ITombstoneFriendly interface that looks like this:

public interface ITombstoneFriendly
{
    void Deactivate();
    void Activate();
}

These will be implemented in a moment.

Hooking into the Page

The best way to manage tombstone events is to hook into the OnNavigatedTo and OnNavigatedFrom overrides in the page code-behind. In fact, because forward navigation always generates a new instance of the view, this is the perfect way to maintain state of the view during navigation even when tomstoning isn't taking place.

Like before, we'll take advantage of some extension methods to make this easy. Here's a little caveat: you may be familiar with some "gotchas" with tombstoning if you've read Jeff Prosise's Real World Tombstoning series (here's part 2, part 3, and Part 4). Oh, and did you know that Sterling automatically serializes WriteableBitmaps using the "fast" technique Jeff describes in those posts? You can easily add one to the tombstone collection and it will serialize for you!

The issue with the pivot index happens due to the order of loading. If you restore values on the view model before the view is loaded, the view itself will reset any two-way bindings and you'll find a pivot simply snap to the first item. This is no good! Therefore, the extension method for the activate waits until the page is loaded, then calls the activate method on the view model.

Here are the extension methods:

public static void DeactivatePage(this PhoneApplicationPage phonePage, IViewModel viewModel)
{
    if (viewModel is ITombstoneFriendly)
    {
        ((ITombstoneFriendly)viewModel).Deactivate();
    }
}

public static void ActivatePage(this PhoneApplicationPage phonePage, IViewModel viewModel)
{
    RoutedEventHandler loaded = null;
    loaded = (o, e) =>
                    {                             
                        ((PhoneApplicationPage) o).Loaded -= loaded;
                        if (viewModel is ITombstoneFriendly)
                        {
                            ((ITombstoneFriendly) viewModel).Activate();
                        }
                    };
    phonePage.Loaded += loaded;
}

The loaded event doesn't take any conditional arguments, so it would be impossible to pass the view model to that event. Therefore, an anonymous method is used instead. By using a local variable, it can be unhooked inside the event call so it is not fired again. Once the page is loaded, the activate method is called on the view model. Because the page has been loaded, binding a pivot control item will work perfectly if the pivot SelectedItem is synchronized with a value on the view model.

Here's what the calls look like from the code-behind for the MainPage.xaml, hooking into the navigation events and passing the correct view model:

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    this.ActivatePage(GlobalManager.GetViewModel<IMainViewModel>());
    base.OnNavigatedTo(e);
}
        
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
    this.DeactivatePage(GlobalManager.GetViewModel<IMainViewModel>());
    base.OnNavigatedFrom(e);
}

Raising the Dead

The only thing left is to perform the actual deed. When the view model is flagged for death, it will hydrate out key values. In this case, it is the current category and current item:

public void Deactivate()
{
    var tombstone = new TombstoneModel();
    if (CurrentCategory != null)
    {
        tombstone.State.Add(ExtractPropertyName(() => CurrentCategory), CurrentCategory.Id);
    }
    if (CurrentItem != null)
    {
        tombstone.State.Add(ExtractPropertyName(()=>CurrentItem), CurrentItem.Id);
    }
    App.Database.Save(tombstone);
}

A new model is created because you never care about the old model - this is saving state for the current tombstone event, and the state from any other don't matter (they will be wiped when the application closes anyway). The dictionary is loaded with the key values for the current catalog and the current item.

Now when the application is revived:

public void Activate()
{
    var saved = App.Database.Load<TombstoneModel>(true);

    if (saved == null) return;

    var categoryId = saved.TryGet(ExtractPropertyName(() => CurrentCategory), 0);

    if (categoryId > 0)
    {
        CurrentCategory = (from c in Categories where c.Id == categoryId select c).FirstOrDefault();
    }
    var currentItemId = saved.TryGet(ExtractPropertyName(() => CurrentItem), 0);            
    if (currentItemId > 0)
    {
        CurrentItem = (from i in Items where i.Id == currentItemId select i).FirstOrDefault();
    }
}

In this case, the category list is always loaded in the constructor of the view model. That doesn't change regardless of tombstoning or not. The items is a filter by category, so when the category is updated, the items filter is also updated. When the old state is loaded, first the category is checked and if it exists, the current category is set to the corresponding category item. The same happens with the item.

That's it. When testing the application, going into a pivot page always returns to the correct pivot column, and the selection state of the list is always maintained. If the application is exited by backing out, the close event deletes the tombstone key and upon re-entering, the pivot and list start on the first page with no selection as expected.

Tombstoning with MVVM can be dead simple with a few helper methods and Sterling to serialize the data.

Jeremy Likness

Sunday, February 13, 2011

An Ultra Light Windows Phone 7 MVVM Framework

I've been doing more work on Windows Phone 7 applications. Because of the smaller footprint of the phone and the way the application is hosted, I don't believe the phone requires the same types of tools and frameworks as the browser. Sharing code and services is something that is obviously important, but while I am a huge advocate of the Managed Extensibility Framework (MEF) and use it in my own Jounce MVVM Framework, I'm not convinced it is needed for smaller phone applications.

So how do I use MVVM on the phone? I'm still exploring options and admit I have not used some of the existing (and probably fantastic) frameworks that are out there. What I did notice immediately was that I would need about six key things to be successful on the phone:

  1. Notify Property Changed — a global requirement for MVVM
  2. Commands — this is fairly universal for data-binding in Silverlight
  3. Dialogs — again, common but easy on the phone
  4. Navigation — a decoupled way to use the phone navigation (not interested in rolling my own due to the stringent "back button behavior" requirements)
  5. Application Bar Bindings — need an effective/easy way to handle getting those icons bound to the view model
  6. Tombstoning — this is every Windows Phone 7 programmer's bane, I handle that with Sterling and will talk more about it in a later blog post.

After working on a few applications, I came up with an extremely light weight framework that is working well for me, so I'm sharing it here. There is no sample project (I am working on one but it's for an upcoming article and not ready to release) but everything you need is here, in source.

Notify Property Changed

The first thing is to create a base class to handle property changed notification. This is almost verbatim the base class that I use in my Jounce framework. You can see the source for it here and it is pretty close to the code that the Prism framework provides in their MVVM guidance.

Commands

I also copied my command implementation, which is close to the DelegateCommand or perhaps RelayCommand implementations you are familiar with. Mine is IActionCommand and you can browse the interface source and implementation source.

A Common Contract

Next, a common contract for view models to address some of the other concerns. The contract looks like this:

public interface IViewModel
{
    IDialog Dialog { get; set; }
    Action<string> RequestNavigation { get; set; }
    Action GoBack { get; set; }
    IEnumerable<IActionCommand<object>> ApplicationBindings { get; }
}

Notice this gives us a decoupled baseline to deal with dialogs and navigation requests. It also returns a list of commands .. called application bindings? Hmmm. Interesting.

A Base Implementation

Next is the base view model, where I add a design attribute and placeholders for the rest:

public abstract class BaseViewModel : BaseNotify, IViewModel
{        
    protected bool InDesigner
    {
        get
        {
            return DesignerProperties.IsInDesignTool;
        }
    }

    public IDialog Dialog { get; set; }

    public Action<string> RequestNavigation { get; set; }

    public Action GoBack { get; set; }

    public abstract IEnumerable<IActionCommand<object>> ApplicationBindings { get; }
        
}

The dialog interface looks like this:

public interface IDialog
{
    bool ShowMessage(string title, string message, bool allowCancel);
}

Next comes the fun part. There may be a case for an inversion of control container here, but I'm going to follow a fairly common pattern but instead of shoving a bunch of variables into the App object, I'll create a GlobalManager class for the MVVM concerns. Now this is a static class and of course that concerns some people for becoming problematic down the road because the views will be tightly bound (plus it's one of those hated singletons). In this case it just doesn't bother me. I unit test the view models, not necessarily the views, and use design-time data in the views. Therefore, the binding for me doesn't pose a threat as I can still grab the view models and run them in isolation while mocking the interfaces.

I'll double the manager as a view model locator and just return a singleton instance of the view models. For data I'll use design time data based on sample data that implements a common view model interface. I'm basically following the pattern from Design-time Friendly View Models with MEF only without the MEF.

The first thing I'll do with my class is provide an extension method for pages to bind to the view model. This method will wire up the dialog and navigation, and also inspect the list of application bindings and wire those up as well. For the most part the view model doesn't need to know about the view, but this is one case where there is a slight dependency: the view model is responsible for knowing the order of the buttons in the application bar so it can return the commands in the correct order. The extension method will then bind the buttons to the commands. Here it is:

public static void BindToViewModel(this PhoneApplicationPage phonePage, FrameworkElement root, IViewModel viewModel)
{
    if (DesignerProperties.IsInDesignTool) return;

    RoutedEventHandler loaded = null;

    var vm = viewModel; // access to modified closure

    loaded = (o, e) =>
                    {
                        var page = o as PhoneApplicationPage;
                        if (page == null)
                        {
                            return;
                        }

                        // unhook loaded so we do this only once
                        page.Loaded -= loaded;

                        // provide an implementation for the dialog
                        vm.Dialog = new Dialog();

                        // provide an implementation for navigation
                        vm.RequestNavigation =
                            newPage => page.NavigationService.Navigate(new Uri(newPage, UriKind.Relative));
                        vm.GoBack = page.NavigationService.GoBack;

                        // bind the view model
                        root.DataContext = vm;

                        // bind the application bar buttons
                        var idx = 0;
                        foreach(var command in vm.ApplicationBindings)
                        {
                            if (page.ApplicationBar.Buttons.Count <= idx) break;
                                     
                            var appButton = page.ApplicationBar.Buttons[idx++] as ApplicationBarIconButton;
                                     
                            if (appButton == null) continue;
                            var command1 = command;
                            command.CanExecuteChanged += (cmd, arg) =>
                                                        appButton.IsEnabled =
                                                        command1.CanExecute(null);
                            appButton.Click += (cmd, arg) =>
                                            command1.Execute(null);
                        }
                    };

    phonePage.Loaded += loaded;
}

As you can see, we do a few things. A local variable hosts the delegate for the loaded event so we can unhook it when done. We link the navigation service from the page to the view model, and then iterate the application buttons. Basically, we do manually what command bindings do automatically, and that's change the enabled state of the button based on the command's ability to execute, and bind the click event to a command execution.

The View Model

What did we accomplish? First we get a view model that has a "save" and "cancel" action that looks like this:

public class MainViewModel : BaseViewModel, IMainViewModel
{
    public MainViewModel()
    {           
        SaveCommand = new ActionCommand<object>(o=>_SaveCommand(), o=>_CanSave());

        CancelCommand = new ActionCommand<object>(o=>_CancelCommand());        
    }                 
    
    public IActionCommand<object> SaveCommand { get; private set; }

    public IActionCommand<object> CancelCommand { get; private set; }

    private void _SaveCommand()
    {
        DoSave();        
        RequestNavigation("/Views/WidgetList.xaml");
    }

    private bool _CanSave()
    {
        return true; 
    }

    private void _CancelCommand()
    {
        if (!Dialog.ShowMessage("Confirm Cancel", "Are you sure you wish to cancel?", true)) return;
        GoBack();
    }

    public override IEnumerable<IActionCommand<object>> ApplicationBindings
    {
        get { return new[] {SaveCommand, CancelCommand }; }
    }
}

Notice the dialog call. Currently, I'm simply using the built-in dialog provided by the MessageBox function on the phone, but the interface allows you to implement it any way you like. Here is my implementation:

public class Dialog : IDialog 
{
    public bool ShowMessage(string title, string message, bool allowCancel)
    {
        return MessageBox.Show(message, title, allowCancel ? MessageBoxButton.OKCancel : MessageBoxButton.OK)
                == MessageBoxResult.OK;
    }
}

The View

Having done all of that, what does it take to actually bind the main page to the view model? Fortunately, with this framework, even using the application buttons and binding them to commands, this is the entire code-behind for the main page:

public partial class MainPage
{        
    // Constructor
    public MainPage()
    {
        InitializeComponent();
        this.BindToViewModel(LayoutRoot, GlobalManager.MainViewModel);            
    }                        
}

The reference to the main view model is type IMainViewModel and is lazy created when referenced the first time.

For nested user controls, I created a similar extension method with the difference that it doesn't bind the buttons as there obviously isn't an application bar for a user control (the view model can just return an empty list or null). To allow the user control to affect navigation, the binding code simply walks the visual tree to the parent to grab the navigation service:

// hook to the navigation of the parent
var parent = VisualTreeHelper.GetParent(control);
while (parent != null)
{
    if (parent is PhoneApplicationPage)
    {
        vm.RequestNavigation =
            newPage => ((PhoneApplicationPage)parent).NavigationService.Navigate(new Uri(newPage, UriKind.Relative));
        vm.GoBack = ((PhoneApplicationPage) parent).NavigationService.GoBack;
        break;
    }
    parent = VisualTreeHelper.GetParent(parent);
}

As I mentioned, I'm still working on various applications to find out what other patterns present themselves, but this to me is a very simple, lightweight, and easy way to get started with the MVVM pattern on the phone.

Jeremy Likness

Friday, February 11, 2011

Sterling Object-Oriented Database 1.0 RTM

In early 2010 I was working on several Silverlight projects that were driven by the need to provide a working offline solution. Isolated storage was the obvious answer. Unfortunately, serializing 10,000 contacts came with some overhead and I realized quickly that I was following some similar patterns when it came to handling large sets of data: I would serialize the key fields (for example, names for contacts) in order to manage lists that I could filter in-memory, while saving the bulk of data for separate serialization events.

This inspired me to create Sterling as a way to ease the burden of persisting data. I looked at other options and didn't like having to change my classes just to save data (for example, make them derive from a database base class when I already was deriving them from my own helper classes). I also didn't like the inflexibility of options available. So, I set out to build something lightweight and non-intrusive that would give the user full control over serialization. The key would be to provide keys and indexes through lambda expressions to make it easy to access common data using LINQ to Object queries in memory while saving the "slow" part (loading from disk) for when it was needed.

I knew I would use Sterling in my own projects but I never imagined how popular it would become with other users. The timing for Sterling was perfect because when the Windows Phone 7 was released, the application developers were faced with a unique scenario called "tombstoning" that requires saving data when the application is swapped to the background. Sterling turns out to be a perfect fit for saving and restoring that data.

After asking some of my peers whether or not it would make sense to provide the solution as an open source community project, the responses were consistent and I realized this was definitely the way to go. I uploaded the bits and quickly went from a fledgling "0.1" release to several interim change sets that morphed into something I was comfortable calling "beta."

That's when the real power of the open source community began to transform the project. Numerous people were pulling down Sterling and using it in their applications, then providing me with valuable feedback for features and bug fixes. Some even sent me code-complete patches to implement various changes. We went from a small set of options for serializing data to a rich, interactive, highly adaptive and flexible solution that can handle a large variety of class configurations and relationships.

It's been a challenging 8 months of late nights fixing bugs, responding to feature requests, and writing a comprehensive guide to make sure the product is well documented, but I would be lying if I said I didn't enjoy every moment. I'm excited to see what the future versions will bring but for now am absolutely ecstatic to announce that I've released Sterling from beta to version 1.0. Enough people have shared the testimonial of their projects and helped me expand the battery of unit tests on both the phone and browser versions to finally make this milestone possible.

You can download the release at CodePlex. You can read the full user's guide at www.SterlingDatabase.com. Please take the time to rate your experience with the product so others know what to expect, and if you are interested in what others are doing or are willing to share your own story, visit our Real World Sterling Projects thread. Thanks everyone and I look forward to exciting features to come.

Jeremy Likness

Thursday, February 10, 2011

Parsing the Visual Tree with LINQ

I noticed a project on CodePlex that provides a "JQuery-like syntax" for parsing XAML. It looked interesting, but then I wondered why it would be needed when we have such powerful features available to us in the existing runtime. Silverlight provides a powerful VisualTreeHelper for iterating elements in the visual tree. It also provides a TransformToVisual function to find the offset of elements relative to other elements.

So first things first: create a function that parses all children in the visual tree. You can either parse specific types of children, or all children that derive from a type and then filter or group on those. The following snippet will handle this:

public static IEnumerable<T> RecurseChildren<T>(DependencyObject root) where T: UIElement
{
    if (root is T)
    {
        yield return root as T;
    }

    if (root != null)
    {
        var count = VisualTreeHelper.GetChildrenCount(root);

        for (var idx = 0; idx < count; idx++)
        {
            foreach (var child in RecurseChildren<T>(VisualTreeHelper.GetChild(root, idx)))
            {
                yield return child;
            }                    
        }
    }
}

So why enumerable? Because sometimes we may want to only get the first item in the list. By making this enumerable, the iterator will stop once the query is done, avoiding the work of recursing n-levels deep. Using some simple LINQ functions, we can now get the first text box in the visual tree:

var firstTextBox = RecurseChildren<TextBox>(Application.Current.RootVisual).FirstOrDefault();

Of course, we might want to parse all of the text boxes:

var textboxes = RecurseChildren<TextBox>(Application.Current.RootVisual).ToList();

Let's try something more interesting. Let's say you have two list boxes and want to move text from one to the other. In order to animate the text blocks, you'll need to put a text block in the main visual tree (outside of the list box) but overlay the list box and then animate to the other list box. How do you get the offset of the text block relative to the list box? Use the visual transform helper. If your list box is referenced as "listBox" then the following will generate a list of tuples that contain TextBlocks and the offset of the upper left corner of the TextBlock from the upper left corner of the ListBox:

var textBlockOverlays = from tb in RecurseChildren<TextBlock>(Application.Current.RootVisual)
                        let offsetFromListBox = tb.TransformToVisual(listBox).Transform(new Point(0, 0))
                        select Tuple.Create(tb, offsetFromListBox);

Now let's have a lot of fun. What about creating a rectangle that overlayss all text retuned by your query? What we need to do is get the upper left and lower right bounds for each text block using the offset from the origin and the width and height, then use a minimum and maximum function to create the rectangle, for example:

var bounds = (from o in
                    (from tb in RecurseChildren<TextBlock>(Application.Current.RootVisual)
                    let upperLeft =
                        tb.TransformToVisual(Application.Current.RootVisual).Transform(new Point(0, 0)) 
                    select Tuple.Create(upperLeft, new Point(upperLeft.X + tb.ActualWidth,
                                                            upperLeft.Y + tb.ActualHeight)))
                group o by 1
                into g
                let minX = g.Min(o => o.Item1.X)
                let maxX = g.Max(o => o.Item2.X)
                let minY = g.Min(o => o.Item1.Y)
                let maxY = g.Max(o => o.Item2.Y)
                select new Rect(new Point(minX, minY), new Point(maxX, maxY))).FirstOrDefault();        

As you can see, the possibilities are endless ... you can easily check for intersections between elements and find any type of element no matter how deep within the tree it is. This will work whether you have nested user controls, content controls, panel items or anything else that can render in the visual tree.

Jeremy Likness

Friday, February 4, 2011

A Pivot-Style Data Grid without the DataGrid

It is fairly common to come across the need for a grid that has dynamic columns and I'm surprised that an open source control hasn't yet been implemented to provide this (or maybe it has ... if so, please share in the comments). I'm not a fan of the DataGrid because it feels very heavy for most of my needs and is also tough to customize when you require very fine control. I almost always go for a Listbox instead. Just check out this article if you don't believe me how powerful they can be.

When the need arose in a recent project to build this type of control I decided to do a spike and see how I could implement it as quickly and easily as possible. While eventually I think it would make sense to build a full custom, templated control for this, the solution using just existing XAML turned out to be relatively straightforward and so I ran with it.

The Problem

The hypothetical problem is that there are user-defined roles and you need a nice grid to allow editing permissions for users. Users can either be in the role, or not. Therefore, you have dynamic rows (users) and columns (roles) to display.

Models

First, you define the models for the users and roles. Because this is a proof of concept application, you can go ahead and generate some test data as well.

The "RoleModel" (pun intended) ends up looking like this, with a nice method to spit out some test roles:

public class RoleModel
{
    private static readonly List<RoleModel> _roleModels
        = new List<RoleModel>
                {
                    new RoleModel {Id = 1, Name = "User"},
                    new RoleModel {Id = 2, Name = "Administrator"},
                    new RoleModel {Id = 3, Name = "Contributor"},
                    new RoleModel {Id = 4, Name = "Operator"},
                    new RoleModel {Id = 5, Name = "Reporter"}
                };
                                                

    public int Id { get; set; }
    public string Name { get; set; }

    public static IEnumerable<RoleModel> RoleModels
    {
        get
        {
            return _roleModels;
        }
    }

    public override bool Equals(object obj)
    {
        return obj is RoleModel && (((RoleModel) obj).Id.Equals(Id));
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}

Obviously in production the static methods and properties won't exist, but this serves for a simple demonstration right now. Next, create the user. In this model, the user contains a collection of roles to which the user is assigned:

public class UserModel
{

    private static readonly List<UserModel> _userModels
        = new List<UserModel>
                {
                    new UserModel {Id = 1, Name = "John Smith"},
                    new UserModel {Id = 2, Name = "Jane Doe"},
                    new UserModel {Id = 3, Name = "Ken Johnson"},
                    new UserModel {Id = 4, Name = "Sue Daily"},
                    new UserModel {Id = 5, Name = "Fred Simmons"}
                };

    public static List<UserModel> UserModels
    {
        get { return _userModels;  }
    }    

    public UserModel()
    {
        Roles = new List<RoleModel>();                       
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public List<RoleModel> Roles { get; private set; }
        

    public override bool Equals(object obj)
    {
        return obj is UserModel && (((UserModel) obj).Id.Equals(Id));
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}

Next there is the intersection of users of roles. This is a model purely to help facilitate the UI by allowing you to get/set a permission. When bound, you can simply parse the results to update the users accordingly - it takes the internal paradigm (a user that just contains the roles it has access to) and translates it to the visual paradigm (an intersection of all users and roles with a permission).

Note the methods to generate these as well - the users are given randomized permissions. This is lazily loaded the first time it is accessed.

public class UserRole
{
    private static readonly Random _random = new Random((int)DateTime.Now.Ticks); 
      
    private static readonly List<UserRole> _userRoles = new List<UserRole>();

    public UserModel User { get; set; }
    public RoleModel Role { get; set; }
    public bool HasPermission { get; set; }

    public long Id
    {
        get
        {
            return (long) User.Id*int.MaxValue + Role.Id;
        }
    }

    private static bool _firstTime = true;

    public static IEnumerable<UserRole> UserRoles
    {
        get
        {
            if (_firstTime)
            {
                foreach (var user in UserModel.UserModels)
                {
                    foreach (var role in RoleModel.RoleModels)
                    {
                        var userRole = new UserRole { User = user, Role = role };

                        if (_random.NextDouble() < 0.5)
                        {
                            user.Roles.Add(role);
                            userRole.HasPermission = true;
                        }
                        _userRoles.Add(userRole);
                    }
                }
                _firstTime = false;
            }

            return _userRoles;
        }
    }

    public override bool Equals(object obj)
    {
        return obj is UserRole && ((UserRole) obj).Id.Equals(Id);
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}

Designing the View Model

Next, the data must be hosted in a view model. In this short example, there is no need for a framework - just implement INotifyPropertyChanged and expose a few properties.

public class MainViewModel : INotifyPropertyChanged 
{
    public class UserModelWithPermissions : UserModel
    {            
        public IEnumerable<UserRole> UserRoles
        {
            get
            {
                return from ur in UserRole.UserRoles
                        orderby ur.Role.Name
                        where ur.User.Id == Id
                        select ur;
            }
        }
    }

    public MainViewModel()
    {
        Width = 800;
    }
   
    private double _width;
    public double Width
    {
        get { return _width; }
        set
        {
            if (value <= 0) return;

            _width = value;
            NotifyPropertyChanged("Width");
            NotifyPropertyChanged("ColumnWidth");
        }
    }

    public double ColumnWidth
    {
        get
        {
            var calc = Width/(Roles.Count() + 1);
            return calc > 0 ? calc : 100.0;
        }
    }

    public IEnumerable<RoleModel> Roles
    {
        get
        {
            return (from ur in RoleModel.RoleModels
                    orderby ur.Name
                    select ur).Distinct();
        }
    }

    public IEnumerable<UserModelWithPermissions> Users
    {
        get
        {
            return UserModel.UserModels.Select(user => new UserModelWithPermissions
                                                            {
                                                                Id = user.Id,
                                                                Name = user.Name
                                                            });
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

There's a bit going on here. First, to synchronize the cell widths for the "grid" there is a Width property that for now is hard-coded to 800 and a ColumnWidth that is computed based on the number of roles.
Conceptually, this is what the grid will look like. There are three lists in play here:

Pivot Grid Example

The first list, across, is a column for each role.

The second list, down, is a row for each user.

The third list (and there are many of these) is a list across each row to fill the values for permissions for each user.

So how do you go about exposing this in the view model?

The roles are easy: just pass through the list. In this case, the roles are ordered by the name to be consistent.
The users are more interesting. Remember, users only had a list of roles that the user has permission to, but the grid requires a column for every role and the ability for the user to check it. What to do?

A simple solution is to shape the data for the view. In this case, a local class is defined (local because it is only scoped/used by this view model) called UserModelWithPermissions. It inherits from the user model. It exposes a single collection of the UserRole model (the one with permissions).

In this example, there is a master list available because the data was set up that way, and the user model simply needs to filter and grab the user roles for that specific user (and order them by the name of the role to be consistent with the columns). In a more practical world, the "data" for user roles wouldn't exist, and instead this would be a join between roles and roles to create the UserRole object on the fly. Either way would work. In the second case the list would need to be stored as an actual collection for data-binding.

The View

Now the view model has what's needed. There is also a strategy in place to show this, so it's simply a question of putting the XAML together. Take a look!

<Grid x:Name="LayoutRoot" Background="White" DataContext="{StaticResource MainViewModel}">    
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>        
    <Grid Width="{Binding ColumnWidth}"/>

At this point, the grid has been defined with a header row and a header column, and the rest is filled. Note the grid that is bound to the column width. What's that for? If you'll notice in the figure above, there is always a cell that is empty in the headers - the very first cell. This grid will fill that slot, so the roles can continue to the right and the users to the bottom of it. Next is the header row of roles:

<ItemsControl ItemsSource="{Binding Roles}" Grid.Row="0" Grid.Column="1">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid Width="{Binding Source={StaticResource MainViewModel},Path=ColumnWidth}">
                    <TextBlock Text="{Binding Name}"/>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

The items list is oriented horizontally, and ends up containing a list of grids all of the same width (as they are bound to the column width). They simply display the role name. With that row out of the way, next is a list of rows for each user:

<ItemsControl ItemsSource="{Binding Users}" Grid.Row="1" Grid.ColumnSpan="2">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="{Binding Name}" Width="{Binding Source={StaticResource MainViewModel},Path=ColumnWidth}"/>
                    <ItemsControl Grid.Column="1" ItemsSource="{Binding UserRoles}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel Orientation="Horizontal"/>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <Grid Width="{Binding Source={StaticResource MainViewModel},Path=ColumnWidth}">
                                    <CheckBox IsEnabled="False" IsChecked="{Binding HasPermission}"/>
                                </Grid>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

You'll notice the users is default list (vertical stack panel) with a user on each row. Each user is actually a grid. The grid cells are again synchronized to be the same width. The first cell is the user's name, followed by a list of cells that represent the permission for each row.

This creates the pivot grid ... but there's something missing. This grid is fixed width (remember the 800 that was set in the view model?) So how can you synchronize the width?

The Synchronization Behavior

The easiest way I could come up with was to use an attached behavior to communicate between the view and the view model. In the view, it could be attached and given an identifier. The view model can then register to receive notifications from that identifier of size.

Take a look. Note this implementation is to show the concept ... a production implementation would use weak references and provide a better mechanism for unhooking the callbacks.

public class SizeSynchronizationBehavior : Behavior<FrameworkElement>
{
    private static readonly Dictionary<string, List<Action<Size>>> _sizeCallbacks 
        = new Dictionary<string, List<Action<Size>>>();

    public static readonly DependencyProperty IdentifierProperty =
        DependencyProperty.Register(
            "Identifier",
            typeof(string),
            typeof(SizeSynchronizationBehavior),
            new PropertyMetadata(string.Empty));

    public string Identifier
    {
        get
        {
            return (string)GetValue(IdentifierProperty);
        }

        set
        {
            SetValue(IdentifierProperty, value);
        }
    }

    public static readonly DependencyProperty TargetWidthProperty =
        DependencyProperty.Register(
            "TargetWidth",
            typeof (double),
            typeof (SizeSynchronizationBehavior),
            new PropertyMetadata(1d));

    public double TargetWidth
    {
        get
        {
            return (double) GetValue(TargetWidthProperty);
        }

        set
        {
            SetValue(TargetWidthProperty, value);
        }
    }

    public static readonly DependencyProperty TargetHeightProperty =
        DependencyProperty.Register(
            "TargetHeight",
            typeof(double),
            typeof(SizeSynchronizationBehavior),
            new PropertyMetadata(1d));

    public double TargetHeight
    {
        get
        {
            return (double)GetValue(TargetHeightProperty);
        }

        set
        {
            SetValue(TargetHeightProperty, value);
        }
    }

    protected override void OnAttached()
    {
        AssociatedObject.SizeChanged += AssociatedObject_SizeChanged;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.SizeChanged -= AssociatedObject_SizeChanged;
    }

    void AssociatedObject_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        TargetWidth = e.NewSize.Width;
        TargetHeight = e.NewSize.Height;

        if (string.IsNullOrEmpty(Identifier)) return;
        if (!_sizeCallbacks.ContainsKey(Identifier)) return;

        // copy to avoid collision if collection modified while iterating
        var callbacks = from c in _sizeCallbacks[Identifier] select c;

        foreach(var callback in callbacks)
        {
            callback(e.NewSize);
        }
    }

    public static void RegisterForCallback(string identifier, Action<Size> callback)
    {
        if (string.IsNullOrEmpty(identifier))
        {
            throw new ArgumentNullException("identifier");
        }

        if (callback == null)
        {
            throw new ArgumentNullException("callback");
        }

        if (!_sizeCallbacks.ContainsKey(identifier))
        {
            lock(((ICollection)_sizeCallbacks).SyncRoot)
            {
                if (!_sizeCallbacks.ContainsKey(identifier))
                {
                    _sizeCallbacks.Add(identifier, new List<Action<Size>>());
                }
            }
        }

        _sizeCallbacks[identifier].Add(callback);
    }
}

The behavior does a few things. First, it attaches to the framework element and listens for size change events. When those are raised, it will set the width and height. Further, it contains a collection of callbacks. When a callback is registered, by passing in a delegate, the size change event will call any registered subscribers and pass the new size.

The behavior is attached like this, on the main grid:

<Grid x:Name="LayoutRoot" Background="White" DataContext="{StaticResource MainViewModel}">    
        <Interactivity:Interaction.Behaviors>
            <PivotGrid:SizeSynchronizationBehavior Identifier="MainGrid"/>
        </Interactivity:Interaction.Behaviors>

Note it is attached and given an identifier. Now, the view model can register for that identifier and update the width appropriately:

public MainViewModel()
{
    SizeSynchronizationBehavior.RegisterForCallback("MainGrid", _MainGridResized);
}

private void _MainGridResized(Size size)
{
    var dispatcher = Deployment.Current.Dispatcher;
    if (dispatcher.CheckAccess())
    {
        Width = size.Width;
    }
    else
    {
        dispatcher.BeginInvoke(() => Width = size.Width);
    }
}

Now the pivot grid will resize with everything else. Download the pivot grid sample here.

Play with the Silverlight application here.

Jeremy Likness