This post is part of a series about creating Windows Store-apps with XAML and C#. Find the Content of the series here:
Windows Store-apps with XAML and C# blog-series
Last weekend I’ve finished the XAML-chapter of my upcoming book about developing Windows Store-apps with XAML and C#. I want to share the things that you should know about the WinRT XAML – the way I call it here - if you’re familiar with Silverlight or WPF.
The WinRT XAML is much like the XAML we know from Silverlight. But there are some differences in WinRT XAML:
- the way you use your custom namespaces is different
- there are some missing things (TypeConverters, Custom MarkupExtensions)
Let’s look at the two parts
Use custom namespaces
There are two ways in XAML to use a namespace:
- 1:1-Namespace-Mapping
- 1:n-Namespace-Mapping
Read the difference for both in Silverlight- and WinRT-XAML below.
The 1:1-Namespace-Mapping
Let’s assume you’ve the following class:
namespace UIRocker.Special
{
public class WindowsEight
{
public bool IsGreat { get; set; }
}
}
To use this class in
Silverlight-XAML, you’ve to add an Namespace-Mapping like this
xmlns:rocker="clr-namespace:UIRocker.Special"
or like this if the CLR-Namespace is in another assembly than the XAML-file containing the Namespace-Mapping below:
xmlns:rocker="clr-namespace:UIRocker.Special; assembly=UIRockerLib"
With the Namespace-Mapping the classes from that Namespaces can be used with the chosen alias. The alias is “rocker” in the snippets above, so the
WindowsEight-class can be used as below:
<rocker:WindowsEight IsGreat="True"/>
In
WinRT-XAML you’re using the class in the same way as above, but the way of creating the Namespace-Mapping is different. Instead of using the syntax with “clr-namespace…” you use:
xmlns:rocker="using:UIRocker.Special"
You don’t care if the Namespace
UIRocker.Special is in another assembly as the XAML-file or not. This works exactly the same way as the using-directive in C#, where you also don’t care if the Namespace is in another assembly than the .cs-File or not. So, great improvement, but creates a little incompability with Silverlight-XAML.
The 1:n-Namespace-Mapping with XmlnsDefinition-Attribute
The Namespace-Mappings above have been 1:1-Mappings. One XML-Namespace was mapped to one Silverlight/WinRT-Namespace.
In
Silverlight-XAML you can create a 1:n-Namespace-Mapping by placing the
XmlnsDefinitionAttribute (Namespace:
System.Windows.Markup) on your assemblies like this:
[assembly: XmlnsDefinition(
"http://thomasclaudiushuber.com/","UIRocker.Special")]
[assembly: XmlnsDefinition(
"http://thomasclaudiushuber.com/", "UIRocker.Mvvm")]
Classes out of the Namespaces
UIRocker.Special and
UIRocker.Mvvm can be used in XAML with one alias by making a 1:n-Namespace-Mapping like this:
xmlns:rocker="http://thomasclaudiushuber.com/"
Unfortunately in
WinRT-XAML there is no possibility for a 1:n-Mapping. The Namespace
Windows.UI.Xaml.Markup contains a
XmlnsDefinition, but it’s not an attribute, it’s a struct and therefore not usable.
Especially when you create a library with many Namespaces in it, it’s great to use just one alias for the library in XAML. Maybe the next Version of WinRT will contain such a mapping. By the way, first versions of Silverlight also didn’t support 1:n-Namespace-Mappings.
Missing things in WinRT-XAML
There are a few other things that are not in WinRT-XAML or behave differently. Let’s take a look at them.
Typeconverters
As XAML is XML, every Attribute contains a string-value. This string-value needs to be converted into the value of the property-type the attribute represents. For primitive types like double, float, int, bool, char etc., the conversion automatically is done by the XAML-Parser (Silverlight and WinRT). Also for Properties of type enum, the XAML-Parser tries to convert the specified string-value into the enum-type of the property. There is also a conversion for some central types hardcoded in the XAML-Parser of Silverlight and WinRT, e.g. the Brush-Type. This conversion allows you to assign a string in XAML where a Brush-Instance is required:
<ListBox Background="Red">
The XAML-Parser takes the “Red”-string, creates a
SolidColorBrush with the
Color Red and assigns it to the
Background-property of the
ListBox.
(Excourse to WPF-XAML: In WPF-XAML this conversion is not done by the XAML-Parser, it is done by the
BrushConverter-class)
Now if you have properties that are of your own type, let’s look at this works in Silverlight and WinRT. Let’s assume we have the classes below:
public class Person
{
public Address Address { get; set; }
}
public class Address
{
public string City { get; set; }
public string Country { get; set; }
}
In
Silverlight-XAML, it is possible to create a
Person-instance as below if a TypeConverter for the
Address-type exists:
<local:Person Address="Müllheim Germany"/>
The corresponding typeconverter could look like this:
public class AddressConverter : TypeConverter
{
public override bool CanConvertFrom(...Type sourceType)
{
if (sourceType == typeof(string))
return true;
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(...object value)
{
if (value != null && value is string)
{
var array = value.ToString().Split(' ');
if (array.Length != 2)
throw new ArgumentOutOfRangeException(
"Invalid format for address");
return new Address
{
City = array[0],
Country = array[0]
};
}
return base.ConvertFrom(value);
}
}
The only thing that is additionally required is to tell the XAML-Parser where to find the
AddressConverter. You do this by specifying the
TypeConverterAttribute either on the
Address-Property in the
Person-class or on the
Address-class itself. Below an example that specifies it on the
Address-class.
public class Person
{
public Address Address { get; set; }
}
[TypeConverter(typeof(AddressConverter))]
public class Address
{
public string City { get; set; }
public string Country { get; set; }
}
So far to Silverlight-XAML, now let’s look at
WinRT-XAML. As mentioned above, WinRT-XAML also supports conversion for
- primitive Types like bool, char, double, int, float,…
- enumeration-values
- central types like e.g. the Brush-type.
If you’ve custom types like the Address-class, currently there’s no support. There’s no TypeConverter in WinRT. Dot.
Markup-Extensions
In Silverlight-XAML it’s possible to create custom subclasses from MarkupExtension and use them in XAML with curly braces. WinRT doesn’t support custom Markup-Extensions. Dot.
Did you find out other bigger differences about XAML?
See you next week with the next post about WinRT and Windows Store-apps.
Thomas