Instantiating a custom object-tree in XAML

XAML, which is short for eXtensible Application Markup Language is a great tool for instantiating objects, not just WPF ones. Although I was aware of this feature for a long time, I never got around to using it exclusively. Recently in one of my projects I wanted to instantiate a simple Object tree, which has WorflowTypes.Workflow as the root type and a property called Screens that stores objects of type WorflowTypes.Screen. I had to create this structure at my application-startup and I was originally doing it by hand. Instead representing that structure in Xaml appeared to be far more convenient.

Here are the two classes:

Workflow.cs

 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4using System.Windows.Markup;
 5
 6namespace WorkflowTypes
 7{
 8    [ContentProperty("Screens")]
 9    public class Workflow
10    {
11        private List<Screen> _screens = new List<Screen>();
12
13        public List<Screen> Screens
14        {
15            get { return _screens; }
16        }
17
18    }
19}
20	
Screen.cs

 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4using System.Windows;
 5
 6namespace WorkflowTypes
 7{
 8    public class Screen
 9    {
10        private string _name;
11        private string _parameter;
12        private string _transition;
13        private Duration _duration;
14
15        public string Name
16        {
17            get { return _name; }
18            set { _name = value; }
19        }
20
21        public string Transition
22        {
23            get { return _transition; }
24            set { _transition = value; }
25        }
26
27        public string Parameter
28        {
29            get { return _parameter; }
30            set { _parameter = value; }
31        }
32
33        public Duration Duration
34        {
35            get { return _duration; }
36            set { _duration = value; }
37        }
38    }
39}
40	
Note that I specified a class attribute called ContentProperty(“Screens”) for Workflow. This tells the Xaml parser to dump all the child nodes of Workflow into the Screens collection. That makes the Xaml very concise. Without that attribute one would have to use the property-element syntax (). Here is the Xaml for creating a Workflow instance:

Default.xaml

 1<loader:Workflow xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 2                                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 3                                 xmlns:loader="clr-namespace:WorkflowTypes;assembly=WorkflowTypes">
 4    <loader:Screen Name="Startup"
 5                                 Duration="0:0:12"
 6                                 Transition="GenieTransition"
 7                                 Parameter="xxx"/>
 8    <loader:Screen Name="Screen1"
 9                                 Duration="0:0:12"
10                                 Transition="FadeTransition"
11                                 Parameter="xxx"/>
12    <loader:Screen Name="Screen2"
13                                 Duration="0:0:12"
14                                 Transition="WipeTransition"
15                                 Parameter="xxx"/>
16</loader:Workflow>
17	
And in my code-behind I use XamlReader to load this Xaml file as:

In Code-Behind

1FileStream stream = new FileStream("Default.xaml", FileMode.Open, FileAccess.Read);
2Workflow workflow = XamlReader.Load(stream) as Workflow;
3	
Although the example is pretty simple, you can see the benefits of using Xaml for creating a complex object tree. If you ever have a need to describe all your objects upfront, doing it in Xaml is recommended. It would save you lot of hand-written code.

A side note

If you look at some of the WPF classes like Panel, in addition to the ContentPropertyAttribute, they also implement the IAddChild interface. However that is obsolete and no longer used by XamlReader. Rob Relyea made a post about this sometime back. It is also mentioned in the docs for IAddChild.