Monday, September 27, 2010

MEF in the Wild: A Retrospective

(Leer en español)

After having worked on several major projects that integrated the Managed Extensibility Framework, I thought it might be beneficial to share a retrospective on how it was used what value it provided. These are all ways MEF helped my team build modular Silverlight applications.

Unlike my earlier post that covered 10 Reasons to use the Managed Extensibility Framework, this is more of an inventory of actual, specific use cases it has been implemented in real world projects, sometimes referred to as "the wild."

Inversion of Control/Dependency Injection

This was perhaps the easiest decision to make. None of these applications had any requirements for more advanced inversion of control or dependency injection than what MEF offers out of the box. Because we were using it for other reasons, and because it is now native to the framework, it was the logical choice to solve this problem. In most cases, it was as simple as defining the interface, importing it where needed and exporting it where satisfied. Other, more specific cases are described below.

Configuration

Configuration was very important and is easy to facilitate with MEF. I included this as a sub-item under IoC because it really is a side effect of inversion of control. By defining a configuration interface, all code could then reference that interface and testing could mock the values. The main application service implemented the configuration and used a combination of compile-time constants as well as parameterized values to load these. Any consumer, application-wide, then simply needed to import the interface to have access to these variables, even from dynamically loaded modules that had no concrete references to any of the assemblies that configuration lived in.

Logging

Logging is another indirect benefit of the IoC pattern that just happened to be implemented with MEF. We created an interface for logging that was satisfied by a logger and maintained the discipline of avoiding "Debug.WriteLine" and instead writing to the log file with severity, source, and additional information. This separation of concerns allowed us to use a simple logging mechanism in the beginning (it could simply write to the debug window) but gave us the flexibility to add service calls, store logs to isolated storage, or otherwise manage the logging transaction easily from one place without changing any of the rest of the application.

Region Management

Prism 4.0 has an excellent region management framework, so I want to be clear that I have nothing against it and am not about reinventing the wheel. For this project, we only had a few specific types of regions defined, so it was more lightweight to use a more specific version.

Essentially, region management consisted of a few pieces. There was an interface for a region adapter that is scoped to a type of container (Grid, or ContentControl, etc). To implement a new region adapter was as simple as inheriting the interface, adding metadata to describe the target container it would support in a MEF export, and then writing the specific events which including registering (pointing a view to a region), activating (making the view appear in the region) and deactivating (making it go away). Some of this involved manipulation of content or child elements but much of it was driven by the Visual State Manager.

An attached property defined a container as a region, and metadata on a view defined what region that view targeted. The region manager aggregated all of these parts and coordinated between them. If I needed a view activated, the region manager would use the chain of responsibility pattern to find the region adapter that owned the view, then ask it to bring it to focus.

[RegionManagerExport(typeof(ContentControl))]
public class ContentRegion : RegionBase<ContentControl>

Read MEF instead of PRISM Part 2 for a detailed explanation of building custom region management, and see Advanced Silverlight Applications using MEF for an example framework.

Service Integration

A common pattern in line of business applications is to have different types of models or business domain objects that can have some common operations performed against them, such as CRUD (create, read, update, delete). For this reason, I was able to create an abstract IServiceFor<T> style interface and define some common functions. Implementations of the contract would export themselves explicitly, and a service router handled mapping the entities to the service handler for the entity.

What this meant is that I could build a view model for an entity and simply request a service from the service router for the entity type and perform all of my generic operations without worrying about how the service was implemented. I could easily stub the service while developing until the endpoints were actually created. Some services actually interacted with isolated storage while others carried messages over the wire: these were all abstracted from the view model and brought together with MEF.

[Import]
public IServiceLocator Locator { get; set; }

var service = Locator.GetServiceFor<T>();

Messaging

Messaging is a very important aspect of any system. For example, consider having a filter view model with filter data that can be applied to other view models. How do these other view models keep track of when the filter changes, or access the filter data?

In this project, we handled messaging in two ways.

View Composition

Something like a filter, even when globally applied, can be considered a part of the view model that use it. It does not make sense by itself, but when it is composed as part of another view model, it has context and use. MEF was extremely helpful with this pattern because any view model that needs access to another could simply import it:

[Import]
public OtherViewModel Other { get; set; }

Of course, that still doesn't allow us to know when it changed, unless we subscribe to the property changed event. That may make sense in some circumstances, but often there are messages so important that many different parts must listen to them. For this purpose, we used the EventAggregator pattern.

Event Aggregator

The event aggregator I used was based on this post, which describes an event aggregator based on Reactive Extensions (Rx). I factored it to work with Silverlight and it worked like a charm.

One common pattern was messages that caused the application to change. For example, a new filter or a new selection item. I created a special class for carrying these messages. It held the type, the payload, and an enumeration. If I wanted to publish a selection event, for example, I could create this class and place the item selected, it's type, and the enumeration for "select" and publish that.

Any "listener" can then filter like this:

var query = from evt in EventAggregator.GetEvent<MyEntityEvent>()
   where evt.Type.Equals(typeof(MyWatchedEntity)) && 
         evt.Action.Equals(Actions.Select)
   select evt.Cast<MyWatchedEntity>(); 

query.Subscribe(myEntity=>{//do something});

Dynamic XAP Routing

Dynamic XAP loading is important in Silverlight applications because it is downloaded from the web and resides on the user's machine. There are two major concerns: the first is the load time for the application, and the second is the memory footprint and impact to the user's machine. Dynamic XAP loading helps by breaking the applicatin into modules. A module is loaded only when requested. Therefore, the initial application loads faster with a smaller memory footprint and grows gradually as modules are exploited.

The challenge some frameworks have is how and when to trigger the module load. I've become fond of a concept I call "dynamic XAP routing." The concept is simple: I tag views with names, either a friendly name or the full namespace. In my core or "infrastructure" project, I have a set of global constants. While the current module may not know about a view, the constants can represent the view. Another set of constants describes the XAP files that are available.

With these two pieces of information, I can then dynamically route via a deployment service that uses deployment catalogs to load modules. A route contains a pointer to a view and the XAP file the view lives in, and is exported by whatever module may need to load that view. When the view is requested, the view manager first checks to see if a route exists. If it does, it asks the deployment service to dynamically load the XAP and defers raising the navigation event until the dependent XAP file is loaded. This makes it easy to abstract navigation from the modules, because any area in the application simply requests the view, and the framework takes care of either navigating to the view, or loading the XAP file and then navigating.

View Model Routing

A common concern with using MVVM is how to bind the view model to the view. In the frameworks I use, there is not a one-to-one mapping because some view models might service multiple views. The view model never really knows about the view(s) it is attached to, but the views depend on the view model (consider it the "binding contract" for the view). Views are exported by type or tag with a target region, and view models are also exported with a view model tag.

Next, I have a simple route object that contains two tags: a view tag, and a view model tag. Whether the view exports this tag, or a separate "routing" class does, these exports are then all managed by a centralized router. The router is able to pull views, and because everything is lazy-loaded, determine if the view needs the view model bound. Conversely, the view model can also be created for the first time or referenced.

The result is that the view and view model binding is completely decoupled - it is described elsewhere in the application. What it also means is that the routing system knows when a view is being shown for the first time, so it can call methods on the view model both the first time it is created, and each time a view is active. This allows my view models to respond to housekeeping that may be required before binding to the view again, without having a dependency on the visual tree.

[ExportAsViewModel(typeof (DialogViewModel))]
public class DialogViewModel : BaseViewModel

...

[ExportAsView(typeof(MyDialog),Regions.DialogRegion)]
public partial class MyDialog
{        
    public MyDialog()
    {
        InitializeComponent();            
    }     
  
    [Export]
    public ViewModelRoute DialogBinding
    {
        get
        {
            return ViewModelRoute.Create<DialogViewModel, MyDialog>();
        }
    }
}

Take a look at View Model binding with MEF and Yet another MVVM Locator pattern for more on this.

Decoupling Views

There are many cases when you may need to map to a type of view but don't know what the view will be before hand. For example, consider a navigation framework that depends on view types (see the next section). When the view is in a dynamic XAP file that isn't loaded, there is no way to directly reference the time. MEF was very useful in "late-binding" types, that is to say, I could import a property for a type using a tag ("MainView" or "DashboardView") and then export the tag when the view was defined somewhere else. This allowed the idea of interacting with a view to be completely decoupled from the actual view type.

Navigation

MEF provided a very flexible navigation framework. I wanted something composable, such that a "navigation event" wasn't limited to a "page" in the application, but rather a view - and views often are nested inside of other views.

The navigation works in conjunction with the view model router to synchronize changes with the view model. In the framework I developed, the MEF-enabled event aggregator simply raises a view navigation event which encapsulates the type of a view and a flag for activation or deactivation. The router, which has imported all views and view models, finds the view, talks to the region manager to swap it out, and if it is active will also call the appropriate method on the view model.

Navigation became incredibly simple because the concept of a dialog or page or even wizard step is reduced to a simple navigation event. The idea of "pop-up" is an implementation detail abstracted from the event itself, and a view model simply raises the request for a view for navigation to happen and doesn't have to worry about view models, regions, or any other nuances of the navigation itself.

Authorization

Authentication and authorization are required for most line of business applications. Typically the user has properties such as roles and credentials that are checked for access and authorization to various areas of the appplication. MEF makes it easy to carry these credentials because the user construct can be exported as either a concrete object or contract, and then imported and queried by any area of the application that requires access to the credentials and user properties.

Commands

Certain commands can be tightly coupled to the user interface, and others might exist in modules not yet referenced. For example, a "home" command or an "expand" command requires a navigation event that is aware of the target for the navigation.

Late-binding Commands

MEF helped handle this scenario by allowing commands to be exported and imported. In some cases, the view model would import the command based on a pre-defined tag (such as a "home" tag) even if the "home" view is in a different module. The module, when loaded, would export the appropriate command and it then becomes avaiable for binding from the view model even though the command was "late-bound" meaning it did not become available until the child module was loaded.

[Import(Contracts.COMMAND_GOHOME, AllowDefault = true)]
public DelegateCommand<object> HomeCommand { get; set; }
...
[Export(Contracts.COMMAND_GOHOME)]
public DelegateCommand<object> HomeCommandExport
{
    get
    {
        return
            new DelegateCommand<object>(
                obj => EventAggregator.Publish(typeof (HomeView).AsViewNavigationArgs()));
    }
}

Global Commands

Some commands are global by nature and instead of creating dozens of local copies per view, make sense to be accessed as a single, global construct. Global commands be exported and then imported wherever they are needed so a global copy is used, rather than creating multiple local instances. Again, as with the "home" example, view models can expose a "home" command before having knowledge of the assembly/module that contains the command, and MEF simply imports the command when it becomes available.

Read Sharing Commands with MEF for more.

Chain of Responsibility

The chain of responsibility pattern is a powerful way to handle common messages that are processed differently based on the message signature. I used MEF to provide a "handler" mechanism that defined a standard contract that would consume certain message types. Each handler would export the contract along with metadata described what messages the handler could process. A central "router" would then import the handlers, listen to the message, and pass the message to the appropriate handlers until one indicated it had successfully processed the message. This, coupled with global commands, provides a very powerful level of extensibility to the application.

For example, consider a "print" command that is globally exposed throughout the applicaton but bound to the data element being printed. Multiple handlers are registered to the print interface that know how to process different types of data objects. When the handler that manages the target object is called, it formats the data in a printer-friendly format and sends the output to the printer. Handling a new type of data is as simple as building a new handler and then exporting the print contract.

Factories with Dependency Resolution

Many classes have multiple layers of dependencies. Consider a composable view where a list of items is presented, and each item is exposed via a bound view model that has dependencies to the event aggregator, service bus, and other contracts that are imported using MEF. MEF makes this scenario simple and straightforward to handle via the ExportFactory keyword. When spinning through a list of data objects, a view model can be created on the fly using the export factory that features full dependency resolution, from handlers to global commands. The data is attached and then the view model bound to the child view with all dependencies resolved via MEF.

Design-Time Friendly Views

Design-time friendly views are extremely important when working with the design team in parallel. MEF made it very easy to build a design-friendly framework because the runtime view models would be bound via the MEF constructs while the design-time view models are bound directly in views using the d:Design and d:DesignInstance attributes. By isolating MEF-specific initialization code using the IPartImportsSatisfied contract, the views and view models remained designer-friendly and would not execute any code reserved for the run time version of the application.

See Design-time Friendly View Models with MEF for more.

Validation Engine

Validation engines typically expose different validation rules that result in rule violations. MEF made it simple and easy to build an engine that was both flexible and extensible. Each validation rule is exported using the contract for the rule. The engine would import all rules, and then provide access via a fluent interface. Read fluent validation with MEF and PRISM to learn more.

Unit Testing

MEF was critical in the success of unit testing because all dependencies were exposed by contracts that MEF imported. For testing, the MEF initializer simply isn't called, allowing the test system to initialize the dependencies using test mocks and stubs. Take a look at using Moq with Silverlight for advanced unit tests.

Conclusion

Obviously, many of these examples could be easily handled using frameworks other than the Managed Extensibility Framework. The framework has the advantage of being included in the language run-time: it's not a third-party, out-of-band release, but a fundamental part of both the .NET 4.0 and the Silverlight 4.0 CLR. Based on my experience building very large line of business Silverlight applications, MEF not only made it easy to break those applications into modules and parts, it also accelerated development time by providing so many features "out of the box," especially the ability to tag exports with meta data and import multiple items for the same contract. Hopefully this will not only provide you with some ideas about how to use MEF in your own applications, but also demonstrates how MEF is being used effectively in production line of business applications.
Jeremy Likness

Thursday, September 23, 2010

Intro to MVVM: Slides and Sample Code

Thanks to everyone who joined me last night for my presentation about Model-View-ViewModel for the Atlanta Silverlight Meetup group. I enjoyed it and appreciate you sticking through the heat (pardon the pun).

As promised, I've uploaded both the slide deck and the code that I demonstrated for you to work with.

  • Click here to download the slide deck (read-only PowerPoint presentation)
  • Click here to download the sample project, which contains the starting project with code-behind ("before") and the same project refactored to use MVVM ("after")

PS - I mentioned this at the talk but realized it wasn't on the decks/this post: the code example starts with John Papa's Feed Reader example that focused on the syndication namespace and isolated storage. I converted it to Silverlight 4, then refactored it to show the same functionality using MVVM. It wasn't originally using the pattern because the focus of the article was on the syndication and isolated storage, not the framework. Thanks, John!

Thanks again and enjoy!

Jeremy Likness

Sunday, September 19, 2010

Hosting HTML in Silverlight (not Out of Browser)

Some Silverlight projects may require that you render HTML content - perhaps a non-Silverlight control or web page. Unfortunately unless the project runs Out of Browser (OOB) the WebBrowser control isn't an option. What can you do?

While there is no easy solution to truly embed HTML inside of the Silverlight rendering engine, it is possible to render the HTML using the browser into a DIV element that is overlaid on your Silverlight application. In fact, because the rendering engine is powerful enough to provide you with all of the sizing events and triggers you need, you can create a very convincing experience displaying HTML in your application - even from the browser.

To illustrate this in action, we'll build a sort of "Silverlight browser" that allows you to navigate to any web page. In reality, we'll load the URL into an IFRAME that lives inside a DIV. What will be important to note is that the DIV automatically moves and resizes when you resize the application, as if it were a part the application itself!

Silverlight Browser

In fact, before we jump into the code, why not click here to check it out yourself? Note that FireFox and IE handle this fine. Chrome creates an infinite loop by placing a scrollbar in the iframe, which resizes it, which then triggers an app resize and ... you get the point. Working with HTML this way in Chrome is fine if you are just injecting the HTML, but using iframes requires some tweaks to avoid scrollbars and set margins for Chrome to behave, and quite frankly I didn't have time to do all of the tweaking for his example.

First, we'll set up the DIV. In order for this to work, we also need to set windowless to true for our Silverlight application, so that we can safely overlay the HTML content. The host page now looks like this:

<form id="form1" runat="server" style="height:100%">
<div id="silverlightControlHost">
    <div id="htmlHost" style="visibility: hidden; position: absolute;"></div>
    <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
  <param name="source" value="ClientBin/HtmlExample.xap"/>
  <param name="onError" value="onSilverlightError" />
  <param name="background" value="white" />
              <param name="windowless" value="true" />
  <param name="minRuntimeVersion" value="4.0.50826.0" />
  <param name="autoUpgrade" value="true" />
  <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50826.0" style="text-decoration:none">
    <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/>
  </a>
 </object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>
</form>

The DIV we'll use is called htmlHost. Notice that we position it absolutely and leave it hidden by default.

Next, we'll create a control for the HTML content. The control will do a few things:

  • It will accept a URL to render
  • It will interact with the DIV to inject an IFRAME that points to the URL
  • It will automatically synchronize the size and position of the DIV to a Grid inside of the Silverlight application

We'll create a control called HtmlHost. In the Xaml, we only define one thing: the Grid we'll use to synchronize with the DIV. Take a look:

<Grid x:Name="LayoutRoot" HorizontalAlignment="Stretch" MinWidth="100" MinHeight="100" VerticalAlignment="Stretch" Background="Aquamarine">
    </Grid>

I gave it a background that contrasts with the rest of the application so you can visually see how the DIV moves as you resize and move the application.

In the code behind, I defined some constants for the attributes to manipulate on the DIV and the markup for the IFRAME. The control has two dependency properties: a HostDiv that points to the id of the DIV it will synchronize with, and a Url to load into the DIV.

namespace HtmlExample
{
    public partial class HtmlHost
    {
        private const string IFRAME =
            @"<iframe height=""100%"" width=""100%"" marginheight=""1"" marginwidth=""1"" src=""{0}""></iframe>";

        private const string ATTR_INNER_HTML = "innerHTML";
        private const string ATTR_LEFT = "left";
        private const string ATTR_TOP = "top";
        private const string ATTR_WIDTH = "width";
        private const string ATTR_HEIGHT = "height";
        private const string ATTR_VISIBILITY = "visibility";
        private const string VISIBLE = "visible";
        private const string HIDDEN = "hidden";
        private const string PX = "{0}px";
        private HtmlElement _div;

        private double _width, _height;

        public static DependencyProperty HostDivProperty = DependencyProperty.Register(
            "HostDiv",
            typeof (string),
            typeof (HtmlHost),
            null);

        public string HostDiv
        {
            get { return GetValue(HostDivProperty).ToString(); }

            set
            {                
                SetValue(HostDivProperty, value);
                if (!DesignerProperties.IsInDesignTool)
                {
                    _div = HtmlPage.Document.GetElementById(value);
                }
            }
        }

        public static DependencyProperty UrlProperty = DependencyProperty.Register(
            "Url",
            typeof (string),
            typeof (HtmlHost),
            null);

        public string Url
        {
            get { return GetValue(UrlProperty).ToString(); }

            set
            {                
                SetValue(UrlProperty, value);
                if (!DesignerProperties.IsInDesignTool)
                {
                    _div.SetProperty(ATTR_INNER_HTML, string.Format(IFRAME, value));
                }
            }
        }

Whenever the host DIV is set, the control grabs an HtmlElement reference to the DIV. Whenever the URL property is set, the DIV is injected with the IFRAME code to point to the URL.

When the control is constructed, we'll wait for it to load, record the current width and height, and then set up the synchronization:

public HtmlHost()
{
    InitializeComponent();
    if (DesignerProperties.IsInDesignTool)
    {
        return;
    }
    Loaded += (o, e) =>
                    {
                        _width = Width;
                        _height = Height;
                        if (_div != null)
                        {
                            Show();
                        }
                    };
}

The synchronization is setup up in the Show method. Here, we set the DIV to be visible. We hook into two events. Whenever the entire application is resized, we'll need to compute a new offset for the DIV. Whenever the grid is resized, we'll need to compute a new height and width. The set up for these hooks looks like this:

public void Show()
{
    _div.RemoveStyleAttribute(ATTR_VISIBILITY);
    _div.SetStyleAttribute(ATTR_VISIBILITY, VISIBLE);
    Application.Current.Host.Content.Resized += Content_Resized;
    LayoutRoot.SizeChanged += LayoutRoot_SizeChanged;
    _Resize();
}

private void LayoutRoot_SizeChanged(object sender, SizeChangedEventArgs e)
{
    _width = e.NewSize.Width;
    _height = e.NewSize.Height;
}

private void Content_Resized(object sender, System.EventArgs e)
{
    _Resize();
}

Notice we're banking on the fact that the only way the grid can be resized is when the application is, therefore we just record the height and width for the _Resize method to use.

The resize is where the magic happens that allows us to place the DIV so it covers our Grid exactly. Take a look:

private void _Resize()
{
    var gt = LayoutRoot.TransformToVisual(Application.Current.RootVisual);
    var offset = gt.Transform(new Point(0, 0));
    _div.RemoveStyleAttribute(ATTR_LEFT);
    _div.RemoveStyleAttribute(ATTR_TOP);
    _div.RemoveStyleAttribute(ATTR_WIDTH);
    _div.RemoveStyleAttribute(ATTR_HEIGHT);

    _div.SetStyleAttribute(ATTR_LEFT, string.Format(PX, offset.X));
    _div.SetStyleAttribute(ATTR_TOP, string.Format(PX, offset.Y));
    _div.SetStyleAttribute(ATTR_WIDTH, string.Format(PX, _width));
    _div.SetStyleAttribute(ATTR_HEIGHT,
                            string.Format(PX, _height));
}

The TransformToVisual gives us a reference to know where our Grid is relative to the entire Silverlight application, which was configured to take up the entire browser window. Doing this, we can compute the offset of the grid from the left and top edge of the application. Then, we can simply take this same offset in pixels and apply it to the top and left style attributes of the DIV. We then apply the height and width, and we're done!

To use the control, I created a simple form that accepts a Url and on the button click will update the control. I used gradients in the background to show how it overlays the Silverlight application. Dropping in the control with a default Url looks like this:

<HtmlExample:HtmlHost Grid.Row="1" x:Name="HtmlHostCtrl" 
Margin="40" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
HostDiv="htmlHost" Url="http://www.jeremylikness.com/"/>

Notice I passed the id of the DIV and a starting Url.

You can see the control in action here (and again, if you are in Chrome, you'll see a LOT of action):

And finally, you can grab the source code by clicking here.

Enjoy!

Jeremy Likness

Wednesday, September 15, 2010

Best Practices for Themes in Modular Silverlight Applications

When building large Silverlight applications, it makes sense to build sets of styles that can be shared across the application. Many examples on the web illustrate placing these in the App.xaml file and then you are off to the races. Unfortunately, when you are building modular applications, it's not that simple. The dependent modules still require design-time friendly views, and to make that happen requires a few steps.

The Central Theme

The first step is to take your theme for the application and place it in a separate project. These are themes that only have dependencies on the core Silverlight controls. What you want is a simple project that any application or module can reference to pull in the theme.

Create a new Silverlight class library, then add a ResourceDictionary to house your themes. In larger projects, it makes sense to break out themes into smaller pieces, like this:

Resource Dictionaries

Then, you can aggregate these into your main dictionary, called Theme.xaml or something similar. It is important that you load the child dictionaries in order. For example, building blocks like colors and gradients will come before more complicated control templates that use the colors and gradients. Your Theme.xaml might look like this:

<ResourceDictionary
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   mc:Ignorable="d">

    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="ColorStyles.xaml" />
        <ResourceDictionary Source="BrushStyles.xaml" />
        <ResourceDictionary Source="TextStyles.xaml" />
        <ResourceDictionary Source="ButtonStyles.xaml" />
        <ResourceDictionary Source="ComboBoxStyles.xaml" />
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

A Point of Reference

As you build your styles, you may end up including references to things like the Silverlight Toolkit or some third-party set of custom controls. This is fine, but you may be surprised when you fire up your project and suddenly the application crashes because it's unable to resolve any styles that have prefixed targets (i.e. data:). The reason has to do with how Silverlight resolves and evaluates references.

The easiest way to manage this is simple:

In your theme project, for every reference you add, right click and choose copy local: false. The references will work, but they won't be associated with that project. In your main project, the one that contains the App.xaml, add every reference that the theme depends on (and leave them as copy local: true). This ensures the DLLs are available when the theme is pulled down.

Setting up the Main Module

In the main module that drives your application, the one with the App.xaml, you can simply reference the theme project and then merge the resources in. Your App.xaml will contain something like this:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>                                
            <ResourceDictionary Source="/MyApp.MyThemeProject;component/Theme.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

The path is known as pack format in its abbreviated form. The first part is the full name of the assembly that the theme resides in. The second part always has component/ followed by the path to your main theme. In this case, ours is in the root. This is all it takes to pull that theme into your application.

Dynamically Loaded Themes

What if you are trying to cut down on load time, so your main application (the one with App.xaml), doesn't have a reference to the theme or the dependent assemblies? This is often the case because the control libraries are rather large. You won't be able to merge the theme in the App.xaml because the required references don't exist.

The solution is to move all of the theme logic to the main module you load after your startup module. A common pattern is to have a small "stub" that is the root application, then show a friendly message to the user while you load the main application components.

First, move the reference to the theme to the module you are dynamically loading. Second, add the dependent references (such as the toolkit) to that module instead of your main module. Finally, when the module is loaded, you'll have to perform some magic to get the theme into the application.

Once the dynamic module is loaded, you will execute this code to pull the theme into the application:

const string MAINTHEME = "/MyApp.MyThemeProject;component/Theme.xaml";
var rd = new ResourceDictionary
                         {
                             Source = new Uri(MAINTHEME, UriKind.Relative)
                         };
Application.Current.Resources.MergedDictionaries.Add(rd);

That uses the same pack notation but programmatically loads the theme into the application-level resources.

Get by with a Little Help from my Blend

Finally, there is one more hurdle to jump. When you create your dynamic modules, you can reference the theme to your heart's content, but the designer isn't going to know about it. Both Blend and Cider (the built-in designer with Visual Studio 2010) rely on hints such as the App.xaml to find themes. Modules don't have their own App.xaml, so the theme isn't found.

If you have a solution for making this work in Cider, let me know - I haven't found anything satisfactory, but I do know what works in Blend.

First, the latest Blend will often come to your rescue the first time you edit the item in Blend. When it finds a missing style, it will prompt you with the following dialog:

Blend Dialog

From there, you can pick which resource dictionaries from which assemblies to use in the designer.

Behind the scenes, Blend creates a file called DesignTimeResources.xaml under the Properties folder. You can create this file yourself if you wish to be proactive about integrating your themes in the designer.

The contents simply contain the now-familiar merged dictionaries that you wish to have available:

<ResourceDictionary
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="/MyApp.MyThemeProject;component/Theme.xaml"/>
    </ResourceDictionary.MergedDictionaries>
    <!-- Resource dictionary entries should be defined here. -->
</ResourceDictionary>

At this point, you should be fine in both runtime and Blend. If anyone nows how to make themes available at design-time in Cider, please let us know through the comments below.

Jeremy Likness

Thursday, September 9, 2010

Design-Time Friendly ViewModels with MEF

The Managed Extensibility Framework (MEF) is a very powerful tool for building modular, extensible Silverlight applications. If you've followed this blog, you'll know that it is not just for applications that anticipate plug-ins, but can be used as an inversion of control container, can facilitate region management, and much more. In preparing the material for my upcoming presentation that is an Introduction to MVVM, I decided to take an existing, publicly available Silverlight application and refactor it to use MVVM.

Everyone seems to like Twitter feeds and RSS Readers, so I chose John Papa's example that demonstrates RSS syndication and isolated storage to refactor. It is an excellent little demo and of course for the article the focus was the syndication and isolated storage, not MVVM.

I'm not going to include the full refactor here - I'll discuss it at the event and then post the code later. What I do want to touch upon, however, is a common issue that people run into when using MEF in conjuction with the Model-View-ViewModel pattern: design-time compatibility. Because the built-in designer for Blend and VS 2010 ("Cider" is the name for the VS 2010 flavor) doesn't actually use the Silverlight runtime, your controls are run in a different CLR than the target application. The result is that MEF compositions fail, which means controls that rely on MEF ultimately don't get rendered in the designer.

Here is our before picture: you can clearly see what the application is going to look like, but there is no data so it's not clear how the data will fit into the control:

MEF Design-Time Before

There are really just a few easy steps to making MEF views design-time friendly. Let's walk through it.

Step One: Create Your ViewModel

This is straightforward and part of the MVVM pattern. Right now, we'll not worry about design-time as much as having a robust ViewModel to use. For my example, I went with a base ViewModel based on the Prism 4.0 drops. The ViewModel itself ended up looking like this:

[Export]
public class FeedsViewModel : BaseViewModel, IPartImportsSatisfiedNotification
{        
    private const string ERROR_INVALID_URI = "Invalid Uri.";
    private const string ERROR_DUPLICATE_FEED = "Duplicate feed not allowed.";

    private bool _add;

    [Import]
    public IFeedStore FeedStore { get; set; }

    [Import]
    public IFeedService FeedService { get; set; }

    public FeedsViewModel()
    {
        Feeds = new ObservableCollection<SyndicationFeed>();           

        AddFeedCommand = new DelegateCommand<object>(
            obj =>
                {
                    _ValidateNewFeed();

                    if (!AddFeedCommand.CanExecute(obj)) return;

                    _add = true;
                    _AddFeed(new Uri(_newFeed, UriKind.Absolute));
                    NewFeed = string.Empty;
                },
            obj => !HasErrors
            );

        Feeds.CollectionChanged += (o, e) =>
                                        {
                                            RefreshFeedCommand.RaiseCanExecuteChanged();
                                            RaisePropertyChanged(() => Items);
                                        };

        RefreshFeedCommand = new DelegateCommand<object>(
            obj =>
                {
                    Feeds.Clear();
                    _RefreshFeeds();
                },
            obj => Feeds.Count > 0);
    }

     public DelegateCommand<object> AddFeedCommand { get; private set; }

    public DelegateCommand<object> RefreshFeedCommand { get; private set; }

    public ObservableCollection<SyndicationFeed> Feeds { get; private set; }

    public int Count { get; set; }

    public IEnumerable<SyndicationItemExtra> Items
    {
        get
        {                
            var query =
                from f in Feeds
                from i in f.Items
                orderby i.PublishDate descending
                select new SyndicationItemExtra {FeedTitle = f.Title.Text, Item = i};

            Count = query.Count();
            RaisePropertyChanged(()=>Count);
            return query;
        }
    }

    private string _newFeed;

    public string NewFeed
    {
        get { return _newFeed; }
        set
        {
            _newFeed = value;                

            RaisePropertyChanged(() => NewFeed);
            _ValidateNewFeed();
        }
    }

    private void _ValidateNewFeed()
    {
        Uri testUri;
        if (Uri.TryCreate(_newFeed, UriKind.Absolute, out testUri))
        {
            if ((from feed in Feeds where feed.BaseUri.Equals(testUri) select feed).Count() > 0)
            {
                SetError(() => NewFeed, ERROR_DUPLICATE_FEED);
            }
            else
            {
                ClearErrors(() => NewFeed);
            }
        }
        else
        {
            SetError(() => NewFeed, ERROR_INVALID_URI);
        }

        AddFeedCommand.RaiseCanExecuteChanged();
    }

    private void _SaveFeeds()
    {
        FeedStore.SaveFeeds(Feeds.Select(feedItem => feedItem.BaseUri).AsEnumerable());
    }

    private void _AddFeed(Uri feedUri)
    {
        FeedService.FetchFeed(feedUri, (ex, feed) =>
                                            {
                                                if (ex != null)
                                                {
                                                    SetError(() => NewFeed, ex.Message);
                                                    return;
                                                }

                                                var oldFeed = (from feedEntry in Feeds
                                                                where feedEntry.BaseUri.Equals(feed.BaseUri)
                                                                select feedEntry).FirstOrDefault();

                                                if (oldFeed != null)
                                                {
                                                    Feeds.Remove(oldFeed);
                                                }

                                                Feeds.Add(feed);

                                                if (!_add) return;

                                                _add = false;
                                                _SaveFeeds();
                                            });
    }

    private void _RefreshFeeds()
    {
        var feedList = new List<SyndicationFeed>(Feeds);
            
        if (feedList.Count == 0)
        {
            FeedStore.LoadFeeds(list=>
                                    {
                                        foreach(var feed in list)
                                        {
                                            _AddFeed(feed);
                                        }
                                    });
            return;
        }

        foreach (var feed in feedList)
        {
            _AddFeed(feed.BaseUri);
        }
    }

    public void OnImportsSatisfied()
    {
        _RefreshFeeds();
    }
}

As you can see, this ViewModel relies on MEF to compose many of its parts. I've pulled out the saving of the feed list to an external service so I can tweak it as needed, and I've also abstracted the call to the syndication service. I've exposed properties and commands and use a query to aggregate the feeds together. This is a lot of functionality and without the required service and storage dependencies, breaks down in the designer. That's OK, there is hope ...

Step Two (Optional): Define an Interface

This might be step one, actually, it all depends on how you work. I like to get my ViewModel working fine, then define the interface and keep up with it. The only purpose of the interface here is to make it easier to define a design-time ViewModel. If you use a tool like JetBrains ReSharper, it's as easy as right-clicking, choosing "Refactor" and then "Extract Interface." We end up with this:

public interface IFeedsViewModel
{
    DelegateCommand<object> AddFeedCommand { get; }

    DelegateCommand<object> RefreshFeedCommand { get; }

    ObservableCollection<SyndicationFeed> Feeds { get; }

    int Count { get; set; }

    IEnumerable<SyndicationItemExtra> Items { get; }

    string NewFeed { get; set; }
}

Step Three: Create a Design-Time ViewModel

Now that we have an interface, we can implement it in another ViewModel we create specifically for runtime. This ViewModel can create new instances of collections and wire in sample data for us. In our example, I've done this:

public class DesignFeedsViewModel : IFeedsViewModel 
{
    private const string DESIGN_FEED = @"http://feeds.feedburner.com/csharperimage/";
    private const string DESIGN_TITLE = "Test Feed ";
    private const string DESIGN_DESCRIPTION = "A test feed for design-time display";
    private const string LOREM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
    private const string FEED_TITLE = "Feed ";

    public DesignFeedsViewModel()
    {
        Count = 10;
        NewFeed = DESIGN_FEED;

        Feeds = new ObservableCollection<SyndicationFeed>();

        for (var x = 0; x < 3; x++)
        {
            Feeds.Add(new SyndicationFeed(DESIGN_TITLE + x, DESIGN_DESCRIPTION, new Uri(DESIGN_FEED)));
        }

        var designItems = new List<SyndicationItemExtra>();
            
        for (var x = 0; x < 10; x++)
        {
            var item = new SyndicationItem(LOREM, string.Empty,
                                            new Uri(DESIGN_FEED, UriKind.Absolute));
            designItems.Add(new SyndicationItemExtra { FeedTitle = FEED_TITLE + x, Item = item });
        }

        Items = designItems;
    }

    public DelegateCommand<object> AddFeedCommand
    {
        get { return new DelegateCommand<object>(); }
    }

    public DelegateCommand<object> RefreshFeedCommand
    {
        get { return new DelegateCommand<object>(); }
    }

    public ObservableCollection<SyndicationFeed> Feeds { get; set; }
        
    public int Count { get; set; }
        
    public IEnumerable<SyndicationItemExtra> Items { get; set; }

    public string NewFeed { get; set; }        
}

Now, a quick note: at this point, you probably realize you could have gotten away with just one ViewModel. In that case, you'd do something like this:

if (DesignerProperties.IsInDesignTool)
{
   // code for design-time
   return;
}

That's perfectly fine but does a lot of mixing of code ... I've grown to prefer keeping my design-time view models separate and synchronizing them with the interface. It's totally up to you!

Step Four: Bind Your Production ViewModel

This is a key step. If you are directly binding the ViewModel in XAML, and using CompositionInitializer to fire up MEF, you'll need to wrap a condition around it so it doesn't fire that command in design time. There are many ways to bind the ViewModel to the view. I've written about a few:

The bottom line is you can bind it however it makes sense. For simple solutions, this is a pattern I've come to enjoy. While it does involve code-behind, it cleanly separates the MEF ViewModel from design-time because it is not invoked in the constructor (this only works if you export the View as well):

[Export("RootVisual",typeof(UserControl))]
public partial class Reader : IPartImportsSatisfiedNotification
{                
    [Import]
    public FeedsViewModel ViewModel { get; set; }

    public Reader()
    {
        InitializeComponent();
    }       

    public void OnImportsSatisfied()
    {
        LayoutRoot.DataContext = ViewModel;
    }
}

Here, I'm taking advantage of the interface that MEF uses when it wires up a class. Once all dependencies are resolved, it will call OnImportsSatisfied and I can glue my ViewModel. In the designer, the control is simply created using new() so there is no MEF call. So how do we get our design-time data?

Step Five: Bind Your Design-Time ViewModel

Binding the design-time ViewModel is actually very straightforward, especially with the help of design-time extensions. At the top of our XAML, we'll two references: one for the design-time extensions if they aren't already there, and one for the location of the design-time ViewModel:

<UserControl
    xmlns:design="clr-namespace:SilverlightSyndication.DesignTime"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    .../>

Next, on the root grid where the ViewModel should be bound, we take advantage of the d:DataContext and d:DesignInstance extensions:

<Grid d:DataContext="{d:DesignInstance design:DesignFeedsViewModel, IsDesignTimeCreatable=True}" ...>

Here we are defining a data context that is only valid at design time. We bind it to a "design instance" of our view model we created specifically for the designer.

Now, when we run the application, MEF finds and binds the production ViewModel for us. However, in the designer, the designer finds and binds the design-time view model. This gives us plenty of rich data to work with and keeps the designer so happy they're likely to buy you a steak dinner (that last was just in case any of the designers I work with are reading this).

With a little Toolkit Theme love, a rebuild, and a refresh of the XAML in the designer, I now get this:

MEF Design-Time After

Jeremy Likness

Wednesday, September 8, 2010

Autofocus Nested Textboxes with Rx in Silverlight

The Problem

A common UI pattern is to expose text in a read-only container, then swap it for an editable input box based on a command. There are multiple approaches to doing this (including just changing the style of the same container). Swapping between a read-only TextBlock to a TextBox is easy enough, but what if you want to also focus and select the TextBox so the user can simply begin typing? And what if the UI elements are nestled deep with in a data template so there is no straightforward way to reference them?

A Solution

I say, "a solution" because there are probably other ones, but this is how I recently tackled the problem.

Unique Identifier

First, I figured no matter how nested the text box would be, it most likely is data bound to some data element. So, in order to uniquely identify the "transaction" I could expose a unique identifier on the bound object. Assume the bound field is "Name":

public string NameIdentifier { get; private set; }

...

// constructor
NameIdentifier = Guid.NewGuid.ToString();

The Message

Using the Event Aggregator pattern, I created a message payload specifically for the "message" that the text item should receive focus:

public class TextFocusEvent
{
    public TextFocusEvent(string identifier)
    {
        Identifier = identifier;
    }
    public string Identifier { get; set; }
}

In the "edit command" we can now publish our message that the text box should receive focus (notice I'm using the DelegateCommand from Prism):

EditCommand = new DelegateCommand<object>(
    obj =>
        {
            if (!EditCommand.CanExecute(obj)) return;

            _oldName = _name;
            IsInEditMode = true;
            EventAggregator.Publish(new TextFocusEvent(NameIdentifier));
        },
    obj => !IsInEditMode);

In this case, you can infer we have an IsInEditMode flag exposed, which we can use to bind the visibility of the TextBlock and TextBox to swap them out. The event saves the old name so if the user cancels, it can be put back. We've just published an event to let the world know that text box deserves some focus. Now let's catch it!

The Behavior

I decided to go with a behavior that could subscribe to the message. Because my event aggregator is based on Reactive Extensions (Rx), instead of being a straight event subscription, it actually returns IObservable, which can be filtered using LINQ. This way an attached behavior can simply listen for the specific identifier it is "tuned" to. We want to databind the identifier because it is generated by the view model, so we expose that property as a dependency property. Here's the behavior:

public class TextBoxFocusListenerBehavior : Behavior<TextBox>
{
    [Import]
    public IEventAggregator EventAggregator { get; set; }

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

    private IDisposable _listener;

    public string Identifier
    {
        get { return GetValue(IdentifierProperty).ToString(); }
        set { SetValue(IdentifierProperty, value);}
    }

    protected override void OnAttached()
    {
        if (DesignerProperties.IsInDesignTool)
        {
            return;
        }

        if (EventAggregator == null)
        {
            CompositionInitializer.SatisfyImports(this);
        }

        if (EventAggregator != null)
        {
            var query = from evt in EventAggregator.GetEvent<TextFocusEvent>()
                        where evt.Identifier.Equals(Identifier)
                        select true;

            _listener = query.Subscribe(evt =>
                                            {
                                                if (AssociatedObject.Focus())
                                                {
                                                    AssociatedObject.SelectAll();
                                                }
                                            });
        }

        base.OnAttached();
    }

    protected override void OnDetaching()
    {
        if (_listener != null)
        {
            _listener.Dispose();
        }
        base.OnDetaching();
    }
}

So what's going on? First, we are importing the global event aggregator (we know this fires on the UI thread, so I'm not using a mutex to check to see if I need to satisfy the imports and request the reference from MEF). To stay design-time friendly, we don't try to compose if we're in design mode.

When the behavior is attached, the subscription is made for the event. Notice, however, that a filter is being used to filter only the identifier we are interested in. When a new event is pushed to us, we simply set the focus and auto-select the text. This has the effect of highlighting the text box so the user can begin typing right away. When the behavior is detached, we dispose of the subscription.

The XAML

Now we can put it all together and attach the behavior in our XAML:

<TextBox Text="{Binding Name, Mode=TwoWay}">
    <i:Interaction.Behaviors>
             <behaviors:TextBoxFocusListenerBehavior Identifier="{Binding NameIdentifier}"/>
    </i:Interaction.Behaviors>
</TextBox>
<HyperlinkButton Content="edit" Command="{Binding EditCommand}"/>

I've left out the nuances of the TextBlock and related code to swap into/out of view, but you get the point ... now, even if the text box is buried within a set of data templates, simple data-binding gives us the way to tie the edit event with the focus behavior. Of course, the event aggregator is a generic approach: you could also create a more strongly typed message contract between the behavior and the event.
Jeremy Likness

Wednesday, September 1, 2010

Hello, MEF for Silverlight Quickstart

Published another quickstart. This is an introductory quickstart for the Managed Extensibility Framework, and is similar to the previous one except that it is specific to Silverlight. You can take a look at the article and watch the short video by clicking here.

Jeremy Likness