Most basic XAML
As part of gaining a deeper understanding of WPF I felt it was important to gain a deeper understanding of how XAML works and what it actually means. Therefore I will attempt to use XAML independantly of WPF…
Naturally my first question was “What is the simplest XAML file I can conceive of?”.
What I came up with was this:
<sys:Object xmlns:sys="clr-namespace:System;assembly=mscorlib"> </sys:Object>
If you create a new Console Application and add a code file called “Test.xaml” then enter the above code it will build. Yipee.
But what does it mean?
I was assuming it creates a new type extending Object, unfortunately since I couldn’t specify a type name I had no way to test that assumption. So from here I wanted to extend my question to include “and I can reflect on”.
A bit more playing landed me this:
<sys:Object x:Class="TestType" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> </sys:Object>
This allows me to create a new type called TestType that extends Object. How do I know this? I can access it from my Main function by calling:
TestType t = new TestType();
Great… so I fire up reflector expecting to find a decompilation giving me:
using System; namespace ConsoleApplication1 { public class TestType : Object { } }
But, no, it is a load more complex than that. What I actually get to see is:
[GeneratedCode("PresentationBuildTasks", "4.0.0.0")] public class TestType : IComponentConnector { // Fields private bool _contentLoaded; // Methods [DebuggerNonUserCode] public void InitializeComponent() { if (!this._contentLoaded) { this._contentLoaded = true; Uri resourceLocator = new Uri("/ConsoleApplication1;component/basictest.xaml", UriKind.Relative); Application.LoadComponent(this, resourceLocator); } } [EditorBrowsable(EditorBrowsableState.Never), DebuggerNonUserCode] void IComponentConnector.Connect(int connectionId, object target) { this._contentLoaded = true; } }
Holy batman and robin. That was not quite what I expected, although the good news is it does indeed create a new type that derives from Object it also implements IComponentConnector.
However, when you stop and think a little it appears that XAML is in fact the conflation of 2 quite different concepts. The first is class definition (what we expected) and the second is Property Assignment (the extra stuff).
I’m assuming therefore that calling InitializeComponent will traverse through the inner XAML setting all the properties of the object.
Unfortunately using Object as the root does not let me test this, so I quickly whip up a simple base class:
using System; namespace ConsoleApplication1 { public class SimpleBase { public string PropertyOne { get; set; } public string PropertyTwo { get; set; } } }
And then modify my XAML to:
<custom:SimpleBase x:Class="TestType" xmlns:custom="clr-namespace:ConsoleApplication1;assembly=" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> </custom:SimpleBase>
NOTE: Notice the use of “;assembly=” at the end of the namespace definition, this is the most conformant way of specifying “look in the current assembly”. It also has the added advantage of making it easy to re-direct later if you refactor the type into a new assembly.
OK, so with that done I can again compile my program and I expect it to be just creating a new instance of TestType (derived from SimpleBase) but not yet setting any properties.
Score one for careful thinking… it does exactly that.
Next up I add a call to on my object t.
TestType t = new TestType();
t.InitialiseComponent();
I would expect this to change nothing since I don’t actually specify any of the properties in XAML.
And indeed it doesn’t, however it does change the hidden field “_contentLoaded” to true.
So for the next test the obvious step is to specify some values for the properties and see if they get set a] before the call to InitialiseComponent or b] after (or c] never…).
<custom:SimpleBase x:Class="TestType" xmlns:custom="clr-namespace:ConsoleApplication1;assembly=" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" PropertyOne="Hello" PropertyTwo="World" > </custom:SimpleBase>
I can tell you now that the expected happens and the values are set after the call to initialise component.
So the first step of understanding XAML is completed.
What is XAML?
It is a conflation of Type Derivation and Property Setting.
Urg, I hate conflations. But OK, it is what it is and that is the future of programming according to MS.
Join me next time to dig deeper into XAML and how to use it.
You must be logged in to post a comment.