Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Learn to Write XAML Applications Today with Xamlon : Page 3

You don't have to wait for Longhorn to explore the benefits of Avalon, the runtime engine that underpins its presentation tier. Xamlon, the most mature third-party implementation of Avalon, lets you build XAML-based applications right now.

Referencing XAML Documents at Runtime
Displaying static data is all very well, but given the graphic complexity exposed by the XAML API, you're likely to want to change things at runtime, too. There's actually more than one way to achieve this, but the most flexible strategy—and the one Xamlon's Knowledge Base endorses—is to add a "class-behind" file that implements the System.Windows.Serialization.IPageConnector interface. IPageConnector contains a single Connect method:

bool Connect(string id, object target)

The easiest way to understand what's required is to walk through an example step by step. First, create a new "Class Library" project and add references to both System.Drawing and to Xamlon.dll (which installs to the c:\Program Files\Xamlon\lib directory by default). Next, implement the IPageConnector interface as follows:

public bool Connect(string id, object target) { switch (id) { case "Window1": MessageBox.Show("Connecting Window1"); System.Windows.Window window = target as System.Windows.Window; window.Width = 300; window.Height = 300; window.AddText( "Text added into Window title"); return false; default: return false; } }

Finally, you need to tell your XAML document to use the interface you have supplied. The XAML runtime will look at any "Mapping" processing instructions you've included in your XAML document to determine which assemblies it should investigate. It will then attempt to query each of those assemblies for an implementation of IPageConnector, using the "Namespace.Class" identifier you may (or may not) have cited in your document with a def:Class attribute. Assuming it locates a suitable class, it will call that class's Connect() method, passing in the ID of the object in question, as well as the object itself. In this case, all I've had to do to get the XAML runtime to call my IPageConnector implementation is to update Example1.xaml so that its def:Class refers to Example2.Example2, and explicitly add an ID attribute to my Window element, because Connect() uses that ID to identify which element is getting connected:

<?Mapping XmlNamespace="Example2" ClrNamespace="Example2" Assembly="bin/Debug/Example2"?> <Window xmlns:def="Definition" def:Class="Example2.Example2" ID="Window1">

Usually, you'd take the opportunity to cache any objects passed into Connect() so that you can explicitly manipulate them later. For demonstration purposes, though, the sample code just resizes the window and changes its title. You'll find the complete project in the Example2 folder in the downloadable sample source.

The TransformDecorator Object
Earlier I pointed out that without special "class behind" code XAML documents don't rescale themselves as they are resized. There's an easy solution, though. Just wrap your Canvas object in a TransformDecorator element, which has a property called Transform. Many of the samples draw on common class-behind code in the assembly zoom.dll for just this purpose. You'll find the source code for zoom.cs in your c:\Program Files\Xamlon\Samples\Vector directory. Having hooked the Window's Load and Resize events using the IPageConnector interface, the class caches the original Window dimensions in its OnLoad handler and recalculates scaling factors in its OnResize handler as follows:

public void Load(object sender, EventArgs e) { System.Drawing.Size size = this._root.ClientSize; this._originalWidth = size.Width; this._originalHeight = size.Height; } public void Resize(object sender, EventArgs e) { System.Drawing.Size size = this._root.ClientSize; double width = size.Width; double height = size.Height; double factorX = (width != 0.0) ? width / this._originalWidth : 1.0; double factorY = (height != 0.0) ? height / this._originalHeight : 1.0; double factor = Math.Min(factorX, factorY); this._zoom.Transform = new ScaleTransform( factor, factor); }

Now open up one of the Vector samples, for example translateTransform.xaml (in the Vector/Transforms subdirectory). The relevant wiring looks like this:

<?xml version="1.0"?> <?Mapping XmlNamespace="Xamlon" ClrNamespace="Xamlon" Assembly="..\Zoom"?> <Window ID="root" xmlns="http://schemas.microsoft.com/2003/xaml" xmlns:def="Definition" def:Class="Xamlon.Zoom" Width="500" Height="80" Load="Load" Resize="Resize"> <TransformDecorator ID="zoom" AffectsLayout="false"> <Canvas> ... XAML primitives ... </Canvas> </TransformDecorator> </Window>

Note, of course, that you'll want to specify initial dimensions for the Window node so that the TransformDecorator starts with appropriate scaling factors.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date