Share via


WPF: Dynamic XAML


The purpose of this article is to highlight some of the many uses for building XAML dynamically at run time.  These techniques are extremely powerful.

If you ever write code which is building something which you can do in XAML then these techniques can save you an awful lot of time.
This is particularly true with things like Trigger based animations which are a complete nightmare to write in code.
This is one of those areas which is really exciting  - so long as you can possibly do it in XAML the limitations are your imagination. 

This is the first in a series of articles.                                                                        

Introduction

Most of the techniques which follow leverage two facts:

  • XAML is xml so you can manipulate and build it as xml
  • You can use XamlReader at run time to dynamically build UI objects from XAML like you can at compile time.

This is an approach with huge potential but used by relatively few WPF developer - if this is new to you then you definitely want to give it a go.

Rather than repeat two versions of everything a fair part of the explanation will be within Gallery samples.  That allows them to be self explanatory if someone comes across them separately.  

This article explains the concepts and broad strokes giving an overview.
The sample articles go into detail.   There are 7 Gallery articles which explain more about the techniques used.

Loading a Flat File as a Resource Dictionary

Even beginners will probably be familiar with merging Resource Dictionaries in app.xaml.

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Dictionary1.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

Perhaps rather surprisingly, where you use a Resource Dictionary like that you can use an uncompiled flat file.  Your Views could be templated and styled in that a way.

This offers the potential to re-skin an application at a fundamental level without re-compiling or re-distributing.
Particularly if you're writing and delivering multi client software packages this has HUGE potential.
Not excited yet?
You can do that merge in a window, control or wherever you can put a .Resources.
And of course if you wanted to you could over-ride resources by having a resource dictionary merged in a more immediate scope.
For example setting a default style for all Datagrids in app.xaml but a different one for a specific Datagrid by loading another Resource Dictionary in it's parent Window.Resources. 
It's also very simple to use.  The limiting factor is thinking up what to put in the resource dictionaries. 
Article and Sample​

Introduction to XamlReader 

XamlReader allows you generate UI from a file, stream or piece of text.
Technically, you can use XamlReader to produce things which aren't WPF UI objects.  XAML defines an object graph rather than "just" WPF UI.  If this is news to you then consider Windows WorkFlow which is defined in XAML . You could potentially invent your own use for it.  

For our purposes, we're going to be putting together XAML which looks very much like one would see in a regular MainWindow.xaml file but dealing with that as a string or xml and then generating UI from that.  At run time. 
This approach is great for generating dynamic UI.  Far easier than doing the same purely in code.  
Similar techniques are used in most of the samples. The idea of this particular one introduces the reader to the basic concepts and gives some tips.

This sample is kept particularly simple so you can understand it easily.   If you take the time to become reasonably confident with basics then that should make understanding the more complicated later samples that bit easier.
Article and Sample

Linq to XML

The following use Linq to XML at various points to manipulate XAML as XML.  LINQ has several specialised variants which you can read about from the link.  If the reader is unfamiliar with Linq to XML it is probably a good idea to at least give this page here a quick read.  As with the above, this should then make it easier to understand the following.

Exploring XML

At first glance you might think you can pretty easily throw XML into a TreeView and explore your Nodes and Attributes. There's a bit of a problem with setting up your HierarchicalDatatemplate to handle this though.  The template is expecting to have a specific type which translates into the name of a node.  If you're exploring arbitrary xml then you won't know that at design time.
If you're only after a fairly simple representation then there's a way round this explained here.
If you want a rather more sophisticated representation of both nodes and attributes then that isn't going to suffice.
Translating xml into XAML is entirely possible and you can iterate down through the nodes and attributes recursively and build TreeviewItems.  This is feasible in code of course.  The advantage offered by the dynamic XAML approach is that it's easier.  You can fairly easily build a proptotype treeview with TreeviewItems exactly how you want them and then split that into templates.  You know what you're going to get because you have the designer support showing you it in Visual Studio.  If you built these in code all sorts of things can go wrong and it's then often quite hard to work out what's going on.
Article and Sample

Changing the Unchangeable

The usual ways to change something dynamically in WPF is to Bind, Style or Template.
There are some things which you can't set in a style - like a style for example !
Templates can change some more things but can be inconvenient if you're looking for a way to apply a style to controls which already have content.
One work round would of course be to introduce a content control with a template.
That can also be impractical at times.
That leaves us with Binding.
You cannot always bind things - for example anything on a freezable.
This is a particular nuisance where you would like to bind attributes like the Value, To or From on an animation.
A specific example of this sort of thing is a re-usable animation that will animate the height of a FrameworkElement between zero and it's usual height on a condition.
This is useful to add a bit of pizzazz to a UI where the user selects adds or manipulates items and you want them or a container they're switched into to grow and shrink.
A particular complication to this is that many such elements will have no specific height - they will usually just grow to the size their contents demand.  There is no height to work with until they're full of stuff.  See Measure and Arranging Children.
Article and Sample.

Flexible Composition

You can compose your entire view and content using these techniques.  This can be.

  • Built on the fly by composing pieces of xml 
  • Read from some pre configured piece of xml

The pieces of xml used to load into XAML can be

  • Read off disk and can get there by self configure, install, file copy or ftp
  • Built into the exe or library you are loading

At an extreme an application could consist of a main page which is entirely empty. This is used as a shell, to be then filled with content dynamically.
In such a system you would have a number of viewmodels - these could be loaded from dynamically downloaded and discovered library or set of libraries.
By one of the options above, the view is composed and an appropriate viewmodel instantiated and presented to the view as the datacontext.

There are two samples, the View Composer Article and Sample to be used dynamically by the Composed View Article and Sample.

Awkward Bindings/Data

Many requirements have a fixed list of fields and they're in a collection of a fairly simple object with a value property translating into a column.  You're looking at one Vehicle or a list of Vehicles.
When the data you are to show is a bit more dynamic this can be a problem.
If you have a variable set of columns to show then you could perhaps build a DataTable  to hold this and use AutoGenerateColumns on a DataGrid.  That would work find if it fits your requirements and you don't care about details of formatting.
When you want a bit more control then you can build your columns in code.
If these are simple columns then it's a bit of a nuisance but still practical.
If these columns have formatting then the code to do this can gets complicated and any issues can be difficult to resolve since you have to unpick objects generated at run time.
Instead of writing code to generate bindings we can create a prototype in the designer and make sure it works OK with sample data.  We can then use that as a template piece of uncompiled XAML and dynamically build UI using that.

The sample for this section shows sales data for the last 6 complete months.   It takes sales data which has been pivotted into a collection of Salesmen, each of which has a collection of sales stats, one per month for the last 12 months.
The XAML for the Datagrid is built as xml and parsed to give a WPF Datagrid.
Article and Sample

Finally

Or not quite.
More exciting techniques with Dynamic XAML are to follow in the second article.