XAML Resources and x:Name
April 28, 2007
New York, N.Y.
About a month ago, I blogged about defining a Name property in a custom class to use the class as an animatable XAML resource. Today while using x:Name to animate resources, I stumbled upon an inconsistency in the workings of loose XAML and compiled XAML.
Here's a XAML file that defines a RectangleGeometry as a resource with an x:Key of "rect". Notice that the geometry includes a RotateTransform which is given an x:Name of "rotate".
-
<!-- ===================================================
RotatingGeometry.xaml (c) 2007 by Charles Petzold
=================================================== -->
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="Rotating Geometry"
Title="Rotating Geometry">
<Page.Resources>
<RectangleGeometry x:Key="rect" Rect="0 0 100 100">
<RectangleGeometry.Transform>
<RotateTransform x:Name="rotate" />
</RectangleGeometry.Transform>
</RectangleGeometry>
</Page.Resources>
<Canvas>
<Path Canvas.Left="150" Canvas.Top="150"
Data="{StaticResource rect}" Fill="Red" />
<Path Canvas.Left="300" Canvas.Top="150"
Data="{StaticResource rect}" Fill="Blue" />
<Path Canvas.Left="150" Canvas.Top="300"
Data="{StaticResource rect}" Fill="Green" />
<Path Canvas.Left="300" Canvas.Top="300"
Data="{StaticResource rect}" Fill="Yellow" />
</Canvas>
<Page.Triggers>
<EventTrigger RoutedEvent="Page.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="rotate"
Storyboard.TargetProperty="Angle"
From="0" To="360" Duration="0:0:2"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Page.Triggers>
</Page>
The resource is shared among four Path elements, and the transform is animated. The result: Four rectangles spinning in unison, as you can see here:
What's interesting is that you can move the x:Name attribute from the RotateTransform to the RectangleGeometry and change the Storyboard.TargetProperty in the DoubleAnimation from Angle to Transform.Angle and it'll still work. Yet, this is now inconsistent with the documentation of x:Name, which states,
-
x:Name cannot be applied in certain scopes. For instance, items in a ResourceDictionary cannot have names, because they already have the x:Key Attribute as their unique identifier.
Now for the kicker: Take that same XAML file (before the modification), add an application definition file, and compile either as an EXE or an XBAP. The source code for the XBAP version is here. (Before compiling, select project properties, then the Signing tab, and click the Create Test Certificate button.) When the XAML is compiled, the x:Name attribute is no longer recognized. Try it:
The "more information" error message says that the "rotate" name cannot be found.
In summary, the loose XAML interpreter is less strict than the documentation: It allows an x:Name attribute in a resource along with an x:Key attribute. But compiled XAML is more strict than documentation: It apparently doesn't recognize an x:Name attribute anywhere within a resource.
Whether the WPF designers intended to allow or prohibit the animation of resources is unknown.