How XAML works
Tuesday, 17 November 2009
Article Index
How XAML works
Properties

Initialising Properties

As with WPF objects in XAML we can set properties on custom objects.

Banner

For example, if we add a trivial int property to MyClass:

public int MyProperty
{
get{return m_MyProperty;}
set{m_MyProperty=value;}
}

we can set this to “20” within XAML using:

<m:MyClass x:Name="MyObject1" 
m:MyProperty="20">
</m:MyClass>

Now if you run the program and examine it after an early breakpoint you will see that the object has been created with the property set to 20.

Notice that the property type implied by XAML is string but the conversion to int is automatically taken care of – essentially by XAML asking the Convert object to convert the string to the type of the property. This is fine as long as Convert has definitions for the appropriate ToType. In addition to converting to the usual primitives, XAML will also try to convert a string to a suitable value of an enumeration by performing string matching against its values.

 

A second problem arises if we are trying to initialise a property that takes a reference type. This is mostly solved by the use of a different property initialisation syntax.

For example, instead of using an attribute to set MyProperty we use:

<m:MyClass x:Name="MyObject1">
<m:MyClass.MyProperty>
20
</m:MyClass.MyProperty>
</m:MyClass>

The result is the same but this syntax is more general because we can include a new object between the property tags.

A demonstration of an object property is a little messy but if we add a new class:

 

public class MyDataClass
{
private int m_MyProperty2;
public MyDataClass()
{
}
public int MyProperty2
{
get { return m_MyProperty2; }
set { m_MyProperty2 = value; }
}
}

This class has a single int property but in principle it could be as complicated as required. Now we can add a new class-valued property to our original class:

private MyDataClass m_MyDataClass;
public MyDataClass MyClassProp
{
get { return m_MyDataClass; }
set { m_MyDataClass = value; }
}

This is just a standard get/set property but it takes an object of type MyDataClass.

Clearly this cannot be set to a new value using a string. The way to do it is:

<m:MyClass x:Name="MyObject1">
<m:MyClass.MyClassProp>
<m:MyDataClass MyProperty2="35">
</m:MyDataClass>
</m:MyClass.MyClassProp>
</m:MyClass>

This creates a new, nameless, instance of the DataClass class and then sets its MyProperty2 to 35. Notice that Attribute setting can be used for MyProperty2 because it is a supported value property however there would be no problem if MyProperty was another reference property – the nesting might get a little deep however!

Implementing a type converter

As an alternative to using nested property syntax to set reference properties, we can opt to handle the conversion from the initialiser string to the object properties ourselves.

Surprisingly this isn’t difficult. For example, suppose we want to allow MyProperty2 to be set by a string. All we have to do is tag the type that the type converter will apply to with:

[TypeConverter(typeof(
MyDataClassTypeConverter))]
public class MyDataClass
{

The rest of the class is unaltered. Now we have to implement the MyDataClassTypeConverter and to do this we need to add:

using System.ComponentModel;

The type converter class has to inherit from TypeConverter and it first implements CanConvertFrom which simply returns true or false depending on whether or not the type converter can do the requested conversion:

 

public class
MyDataClassTypeConverter:TypeConverter
{
public override bool
CanConvertFrom(ITypeDescriptorContext
context, Type t)
{
if (t == typeof(String)) return true;
return false;
}

The second method we need actually does the type conversion:

 public override objectConvertFrom(
ITypeDescriptorContext context,
System.Globalization.CultureInfo
culture,object val)
{
MyDataClass temp=new MyDataClass();
temp.MyProperty2= Convert.ToInt32(
(string)val);
return temp;
}
}

Notice that it creates a new instance of the class that it performs type conversion for and then processes the string to initialise the properties of the MyDataClass instance. Notice also that the Type converter creates and then initialises the object to be stored in the property using the information supplied by the initialisation string.

Clearly a real example would be more complex and would parse the string to extract multiple items of initialisation information.

With the type converter in place we can create an instance of MyClass using:

<m:MyClass x:Name="MyObject"
MyProperty="23" MyClassProp="35" >
</m:MyClass>

Beyond initialisation

Suppose you want to make use of the objects created by the XAML in your code. The attribute:

x:Class="WpfApplication1.Window1"

defines the partial class that provides the “code behind” support for the XAML. Within this class all of the objects you have created are within the namespace and accessible.

For example you can write, without any other modifications:

private void Window_Loaded(
object sender,RoutedEventArgs e)
{
MessageBox.Show(
MyObject1.MyProperty.ToString());
}

You can similarly write code that manipulates any object or property initialised by XAML.

Where next?

It is clear that XAML is a very general and extensible object instantiation language. If you follow the example in this article I can promise you lots of difficulties caused by synchronisation – the project organisation used in this article was adopted to make the example simple and thus falls over in the real world. The problem is that XAML doesn’t expect the assemblies that contain the classes it is instantiating to change during development. This is easily cured by splitting out the class definitions into another assembly.

 

In the final analysis you have to ask yourself if XAML is worth it. Is it really so much better to instantiate objects declaratively with all of the type conversion and namespace problems this brings about? Even if you decide it isn’t, armed with the knowledge of the “bigger picture” the way XAML works with both WPF and Silverlight should be much easier to understand. You might even want to create custom designers for your own sub-space of XAML.

Banner


FlexGrid - A Lightweight Data Grid

There are more data grids available than the standard one that comes with WPF. In this article we take a look at FlexGrid for WPF and discover how easy it is to use.


<ASIN:0470041803>

<ASIN:1590599624>

<ASIN:3939084603@DE>

<ASIN:0321374479>



Last Updated ( Friday, 19 March 2010 )
 
 

   
RSS feed of all content
I Programmer - full contents
Copyright © 2014 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.