So my last XAML basics post ran aground when I couldn’t get custom objects to accept pure textual content. Since that time I’m glad to say a concerted documentation reading effort unearthed a little gem: Pure textual content can only be used when the enclosing type is defined in a separate Assembly.

Why is that? Haven’t got the foggiest idea but suffice it to say it probably won’t be a significant issue in normal use since the only reason to use Xaml is likely to be working with some kind of framework (WPF, WCF, etc) that will come wrapped in its own Assembly anyhow.

So having made the tweak to put my SimpleBase class in a separate VS Project (==Assembly) and licked the text issue I want to press on probing the rest of the xaml-space.

Event Handlers

First up on the hit list were EventHandler wiring, e.g.

<custom:SimpleBase x:Class="TestType" 
                    xmlns:custom="clr-namespace:ConsoleApplication1;assembly="
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                   OnClick="HelpHandler">
</custom:SimpleBase>

after some Reflection I can report that it works just like you would expect – it adds a delegate to the HelpHandler method to the SimpleBases OnClick event when you call the InitialiseComponent method of the SimpleBase instance. Nothing fancy going on here – nice 🙂

x:Name

Then we get on to a bit of cleverness, introducing variables/properties using x:Name. This is kind of strange because it gives a completely different meaning to an attribute than normal – normal attributes in xaml are (best I can tell) evaluated during the InitialiseComponent call. x:Name however actually adds new members to the type being defined (further conflating the two concepts).

What type of member does it add? Actually it seems to Infer the type it needs to be from the type of the object being named, thus <Button x:Name=”Quest”/> will create an internal member variable of Type Button called Quest. The value of this variable will still only be set during the call to InitialiseComponent.

OK, accepted, but what happens if we name a button inside a grid inside a xaml element? To find out I created some simple types and did some more reflecting.

<custom:SimpleBase x:Class="TestType"
                    xmlns:custom="clr-namespace:ConsoleApplication1;assembly="
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <custom:SimpleTypeOne x:Name="SimpleVarOne">
        <custom:SimpleTypeTwo x:Name="SimpleVarTwo">
        </custom:SimpleTypeTwo>
    </custom:SimpleTypeOne>
</custom:SimpleBase>

The result is that both SimpleVarOne and SimpleVarTwo are declared as internal member variables of the TestType class. Or in other words nesting of the XAML appears to have no impact on the declaration of the members. In many respects I’m not sure what else it could mean but it is certainly interesting and worth keeping in mind.

Summing up

I have one more thing to investigate in this line for which you should tune back in next time, however XAML is now more of an open book to me and hopefully you. To summarise:

Xaml is a conflation of Type Derivation and Property Assignment.

The Root Element specifies the Base Type and via the x:Class attribute the name of the New Type.

Any element can be named with the x:Name attribute and this has the effect of creating an internal member variable with the given name and the Type of the element on which it is applied.

The Type is compiled at compile time, but the properties are not set until an instance is a) created, and b) initialised with a call to InitialiseComponent().

The Type created by the xaml is automatically marked as Partial, this is what allows us to have the code-behind file. The code behind is nothing more than another partial class with the same name.

If you look at the auto-generated xaml code behind file you will find the call to InitialiseComponent slipped into the constructor where it can perform its magic on type instantiation.

see also