Tuesday, October 11, 2011

Quick Tip: Design-Time Views for Regions

If you've worked with the Region Management pattern before, one source of frustration can be the lack of a design-time view. While you can compose individual views to be designer-friendly, the aggregate views that mark regions often end up devoid of anything useful. A simple little trick, however, can change that.

You may be familiar with creating design-friendly view models, but the extensions for Blend work the same with views. For example, consider a main page that has a layout divided into regions that are marked by content controls, like this:

<ContentControl  VerticalAlignment="Center" Margin="20 0 0 0" region:ExportAsRegion.RegionName="SortRegion"/>

There may be one or many views that can fit in the content control, but having it completely empty just doesn't make a good design experience as you cannot tell how components will fit together. With just a little tweak, however, you can change that. Consider this approach instead:

<ContentControl  d:DataContext="{d:DesignInstance Views:SortView,IsDesignTimeCreatable=True}" Content="{Binding}"
VerticalAlignment="Center" Margin="20 0 0 0" region:ExportAsRegion.RegionName="SortRegion"/>

This simple change has done a few things. First, it binds an instance of a reference view to the data context of the control. The binding will only be invoked in the designer and will not be impacted during runtime. Second, the content control is set to the binding, which is the view in the designer, causing it to render the content. With just that simple tweak you now can see how a view will fit into the region!

The view is created directly and is not recursively wired into the design-time experience, so any design-time data within the referenced view will not appear. To get around that you'll need to create a mock view instead and create an instance of that. If the view isn't activated right away, the content control will end up hosting whatever it inherits from the data context of its parents, which may have undesired side effects, but in most cases you will likely activate the view that routes to the region before any artifacts are visible to the end user. If you need to, you can also manually set the data context (the "real" data-context, not the design-time one) to {x:Null} to prevent it from inheriting anything at runtime.

Finally, there is always the option to use a custom markup extension if you really need a more robust view. For me, the trade-off of making a simple tweak is worthwhile.

Here's the design-time view of a small control, showing sample data:

Here's the main page with nothing but regions and design-time views. While the design-time data isn't wired, the views fall into place and I can get a sense of the overall layout (click to see a larger image):

And finally this is the same application at runtime:

So now you don't have to suffer from regions turning their backs on your designer. Enjoy!

Jeremy Likness


  1. Is that a freely available XAML theme you're using in the UI examples there cuz they look pretty sweet and I'd love to get my hands on them.

  2. Yes! My design skills are limited to stick figures in UML diagrams. The theme you see is "Jet Pack" here is the preview: http://www.silverlight.net/content/samples/sl4/themes/jetpack.html

  3. Awesome thanks for the link to Jet Pack!