I have thought that in the future to write more posts in English. I know that all my Swedish readers have no problem with it.

Sometimes you want more flexibility to adapt the user interface for the data you download from a Web service. With dynamic loading of XAML one can both send data and a description of how this data should be displayed. With templates, you do not build the user interface and insert the data in the on the server side. One can instead bind the user interface and the data on the client side.

In this article I will show you how to load XAML from a local xml file. (In reality, this xml obviously come from a Web service.) I also want to show you how to get bindings to work to show the data.
The important method to get this to work is called XamlReader.Load, which takes a string of valid XAML code and creates an object structure of it.

With valid XAML code means:

  • The XAML content string must define a single root element.
  • The content string XAML must be well formed XML, as well as being parsable XAML.
  • The required root element must overpriced specify a default XML namespace value. This is typically the Windows Phone namespace, xmlns = “http://schemas.microsoft.com/winfx/2006/xaml/presentation”. This XML namespace is explicitly required in Windows Phone.

One can make use of well-formed XML to describe XAML. In my example, it means that I create a standard XML document and this creates my XAML.

I would emphasize again that one needs to have the attribute xmlns = http://schemas.microsoft.com/winfx/2006/xaml/presentation in the root element object.

<?xml version="1.0" encoding="utf-8" ?>
<Border xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    ...
</Border>

Example

The example can be downloaded here LoadDynamicUIPhoneSolution

XML file

The xml file look like this
   1:  <?xml version="1.0" encoding="utf-8" ?>
   2:  <Border xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:          Padding="10, 7, 10, 10" BorderBrush="#FF4F6261" BorderThickness="1.5">
   4:    <StackPanel>
   5:      <Border Background="#FF070709" CornerRadius="2"
   6:              BorderThickness="2" BorderBrush="#FF2D3A3A">
   7:        <TextBlock Text="{Binding Station}" Foreground="#FFFBFDFE"
   8:                   TextWrapping="Wrap" FontWeight="Bold" TextAlignment="Center" />
   9:      </Border>
  10:      <ItemsControl ItemsSource="{Binding Items}">
  11:        <ItemsControl.ItemTemplate>
  12:          <DataTemplate>
  13:            <Grid>
  14:              <Grid.ColumnDefinitions>
  15:                <ColumnDefinition Width="10"/>
  16:                <ColumnDefinition Width="*"/>
  17:              </Grid.ColumnDefinitions>
  18:              <Rectangle Grid.Column="0" Fill="LightGreen"
  19:                         VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
  20:                         Margin="0,13,4,4" />
  21:              <Border Grid.Column="1" Margin="0,10,0,0">
  22:                  <TextBlock Foreground="#FFD6CB46" FontWeight="Bold" TextAlignment="Left"
  23:                             FontFamily="Segoe WP Bold" Padding="4" FontSize="15">
  24:                    <Run Text="{Binding Next}"/>
  25:                    <LineBreak/>
  26:                    <Run Text="{Binding Later}"/>
  27:                  </TextBlock>
  28:              </Border>
  29:            </Grid>
  30:          </DataTemplate>
  31:        </ItemsControl.ItemTemplate>
  32:      </ItemsControl>
  33:    </StackPanel>
  34:  </Border>
This is a template that is used to display train information for a metro train system. It’s a one-to-many relationship between the station (here is example as the binding Station [7]) and information about several trains that will depart from this station. To display this relationship have I created a ItemsControl [10], that binds to the collection Items [10] and for each item do I display the property Next [24] and Later [26].

Read XML file

   1:  private string loadXamlFromFile()
   2:  {
   3:      StreamResourceInfo strm = Application.GetResourceStream(new Uri("xamltemplates/metro.xml", UriKind.Relative));
   4:  
   5:      XElement x = XElement.Load(strm.Stream);
   6:  
   7:      return x.ToString();
   8:  }

Reading of the XML file is encapsulated in a method named loadXamlFromFile. It returns string because XmlReader.Load reads a string.

Create the data structuer that will be bind to the template

This is done in a simple way. The information consists of two classes, one of the station (StationData) and one for the traffic (TraficInformation).

   1:  public class StationData
   2:  {
   3:      public string Station { get; set; }
   4:      public ObservableCollection<TraficInformation> Items { get; set; }
   5:  }
   6:  
   7:  public class TraficInformation
   8:  {
   9:      public string Next { get; set; }
  10:      public string Later { get; set; }
  11:  }

I fill these classes with the following code:

   1:  StationData vm = new StationData()
   2:      {
   3:          Station = "Humlegården",
   4:          Items = new ObservableCollection<TraficInformation>()
   5:              {
   6:                  new TraficInformation() { Next = "18 Farsta Strand 1 min",
   7:                                            Later="19 Hagsätra 5 min"},
   8:                  new TraficInformation() { Next= "19 Hässelby str.",
   9:                                            Later = "18 Vällingby 5 min"}
  10:              }
  11:      };

And store it in a variable with the name of vm, for ViewModel.

Do the magic

The app has an event handler registered (commandLoadDynamicUI) for a buttons click event.

   1:  private void commandLoadDynamicUI_Click(object sender, RoutedEventArgs e)
   2:  {
   3:      string metroTemplate = loadXamlFromFile();
   4:      var metroXaml = XamlReader.Load(metroTemplate);
   5:  
   6:      StationData vm = new StationData()
   7:          {
   8:              Station = "Humlegården",
   9:              Items = new ObservableCollection<TraficInformation>()
  10:                  {
  11:                       new TraficInformation() { Next = "18 Farsta Strand 1 min",
  12:                                                 Later="19 Hagsätra 5 min"},
  13:                       new TraficInformation() { Next= "19 Hässelby str.",
  14:                                                 Later = "18 Vällingby 5 min"}
  15:                  }
  16:          };
  17:  
  18:      (metroXaml as FrameworkElement).DataContext = vm;
  19:      gridOfContent.Children.Add(metroXaml as UIElement);
  20:  }

[3] call the method that loads the XML file and returns a string which is saved into the variable metroTemplate. At row [4] we call XamlReader.Load with that string and we get an Object variable is returned. [6 – 16] is the loading of the data that I described before.

At row [19] I add the XAML object structure, that XamlReader.Load returned, into an existing object tree. I have chosen to use a Grid as this object, but you can use any xaml objects that have a Children property.

Row [18] sets the DataContext for the root element object that was defined in the XML file.