Runtime XAML generation

I know what you are thinking: Woah! A new blog post this soon? Its only years since the last one; where do you find the time?
Writer’s block? Lazy? Just useless? Anyway! I’ve been wanting to do this post for a while now; hopefully it’s of use to someone.

Background

While working on a client project, we came to a point where we needed to generate UI at runtime to support templating of forms.

The scenario is this:
We have a wizard component that guides a user through data input and analysis which is a set of sections and pages with input fields, workflow statuses, data visualizations, etc.
However, a customer of the software may need to customize this process to their company requirements or even create a new process.

Now, we don’t want to upload XAML markup to the backend which would allow too much editing freedom (this is something the customer should be able to do themselves without involving expensive template-designing consultant fees) nor do we want XAML in the backend because the client app could be replaced/supplemented with another app on a different platform.
So, the template is a JSON format which does not deal with the specific client-side implementation. Which gives us even more benefits such as validation of uploaded templates (kind of hard with a XAML dump) and the payload is small and fast to deal with.

That’s the quick and generic overview of this.

Solution

First off: The code for this is my client’s property so I cannot share it here without permission.

I got the idea after a friend was talking enthusiastically about Monoids.
My thought was this: XAML elements are DependencyObjects which can only be created on the UI-thread and it’s a bit of a hassle to deal with the structure as you initialize it all.
I didn’t want to create all the elements, add the elements to their parent StackPanels, Grids, etc and it all becomes very sequential and annoying to deal with.
Furthermore, if some part of the UI generation required some async work it all becomes an issue with these DependencyObjects.

So I played around with creating this XAML describing class which behaved as a monoid. The reason for that is that the XAML element (such as a textbox) can be dealt with on its own, in a parallel thread or however you want it.
When all of the elements are done parsing, they can be combined in any sequence they feel like because each element knows who it is and who their desired parent is.
This information comes from the template – basically, a group of fields is given id 1 (and in the app is considered to be a container such as a StackPanel) and the fields that belong to that group get their own ids with a parent id of 1.
Having this information means that each element can return from wherever they come from in any order and for final combination it will all fall into place.

In short, the code could look like this for declaring some XAML controls:


var field = XamlElementDescriptor<TextBlock>.Create(groupId: null, parentGroupId: 1);

field.AddProperty(“Text”, “asdf”);

 


var container = XamlElementDescriptor<StackPanel>.Create(groupId: 1);

container.AddProperty(“HorizontalAlignment”, “Stretch”);

 

To combine them it would be a matter of just adding them together:


var combinedElements = field + container;

 

And render it: var xaml = XamlWriter.Render(combinedElements.First());

 

combinedElements.First() will be the StackPanel with the TextBlock inside it.
And the output of the parsing results in a simple:


This also supports custom controls and attached properties, of course, and will add the necessary namespaces to the XAML markup to make use of them.

A slightly more complex example to demonstrate this could be something like this:

 

var field = XamlElementDescriptor<TextBlock>.Create(groupId: null, parentGroupId: 1);

field.AddProperty(“Text”, “asdf”);

 


var container = XamlElementDescriptor<StackPanel>.Create(groupId: 1);

container.AddProperty(“HorizontalAlignment”, “Stretch”);

 


var grid = XamlElementDescriptor<Grid>.Create(groupId: 2, parentGroupId: 1);

grid.AddExpandedProperty(“Grid.ColumnDefinitions”, new
XamlElementDescriptorCollection {


XamlElementDescriptor<ColumnDefinition>.Create(),


XamlElementDescriptor<ColumnDefinition>.Create()

});

 


var image = XamlElementDescriptor<Image>.Create(parentGroupId: 2);

image.AddProperty(“Source”, “/Assets/blabla/etc.jpg”);

image.AddProperty(“Stretch”, “UniformToFill”);

image.AddProperty(“Grid.Column”, “0”);


var combinedElements = container + field + grid + image;

 

 

 


var xaml = XamlWriter.Render(combinedElements.First());

Using XamlReader now to instantiate the controls is now just a walk in the park.

That is the quick run-down of my solution for this – and it may not be the best (any input would be appreciated), but it works really well and its really fast.

Oh, you may be thinking “Well, this is error prone as adding properties using strings can cause runtime exceptions if typos are introduced and the like”.
The sexy lady Roslyn helps us there! I wrote an extension that validates this and provides errors and simple code fixes.

Or even custom attached properties (with a code fix):

 

I might do a follow-up blog post how the Roslyn analyzer was written; maybe quite fast if there’s any interest in it.

Advertisements

Back to square one

I’m a “noob”. Thats basically the feeling these days as I’m playing around with XNA for WP7. But its fun and its easy. After years of doing enterprise development this is a nice change of gears; it lets me take a break from my every day routine of SharePoint and such.

I’ve always considered game development to be the place where I could fully let loose and enjoy some cutting edge code, but the industry is hard to get into – especially for beginners. WP7 changes that, of course, as it allows everyone with varied .NET backgrounds to join in on the fun.
Full XNA development puts alot on the plate what with shaders and such, but with WP7 you get an entry level introduction to game development (and yet you get to play with advanced concepts such as sensors and touch in an easy way). I’ve done some shader coding; just enough to understand that I’m actually happy XNA for WP7 doesnt support more than what is included (for now) because otherwise I’d charge that hill as well and for now I’m happy with enjoying the basics.

While XNA is a platform that provides a lot of help its still not the big babysitter like the other platforms I use every day. It gets you started with the fun stuff and hiding all the low level code which deals with the hardware etc. My first realization was that doing input management and control UI is something that you need to handle yourself. There is a certain measure of infrastructure code that you need to put in place before you get to play with the fun stuff; not like, for example, Silverlight where you can just draw a button and attach to a click event.
But its worth it because you gain a deeper understanding of what the babysitter platforms actually do for you and leaves you a better developer. I firmly believe its important for developers to know what a framework actually does for them.

XNA for WP7 (as that is what I work with at this moment) is just easy enough to do simple games and challenging enough so that I have something to pit my mind against when doing more advanced games.

Hopefully I’ll have some good ideas worth publishing on the Marketplace soon as my number one ambition, still and always, is to create something that people enjoy whether it be for entertainment or business.

In reality this isn’t back to square one because with my .NET backround WP7 development, be it Silverlight or XNA, is easy – just enjoy it, people.