I've been playing with 3D and Animation recently trying to better understand all of the parts and pieces. And the 'NameScope' class seems to be an important part of the glue that eases the transition between xaml and the C# code behind.

My objective in this tutorial is to better understand the NameScope class and how it enables xaml code and C# code to obtain the same results.

In .Net 3.5, NameScope implements the INameScope interface methods which are 'FindName', 'RegisterName', and 'UnregisterName'. The 'Name' the methods refer to are the 'names' of the objects defined in the project's xaml. In the code behind, you can find these objects using 'FindName' and providing the object's text name.

So I started out with a simple WPF Application project. I named mine "WPFNameScopeProject". Then I added 'Name="mainWindow"' and 'Loaded="mainWindow_Loaded"' to the <Window> element, changed the <Grid> element to <StackPanel>.

I want to be able to write information to the Console so I also changed the application's 'Output type' in 'Project>Properties' from 'Windows Application' to 'Console Application'.

I've attached a screenshot of the Console window so you can see that in a normal WPF Application, there is already a 'NameScope' object defined. It turns out that if your application is not a WPF Application, you do not automatically have a NameScope object. If you are writing a Console Application or a WPF Application from scratch but you can create one with the line

NameScope.SetNameScope(mainWindow, new NameScope());

The interesting thing here is that the names of the mainWindow and stackPanel objects in the NameScope object are the same as the names of the objects you would refer to in the code behind.

But you might have noticed that not all classes have a 'Name=""' property that you can specify. For instance, create a button in our <StackPanel> with the following xaml code:

If you try to specify a 'Name=""' property for the <TransformGroup>, <TranslateTransform>, <ScaleTransform> and RotateTransform> elements the intellisense doesn't show you a 'Name=""' property. But you can specify an 'x:Name=""' property. I've added the x:Name properties in the following xaml code:

I've enumerated through each of the TransformGroup's Children to find the RotateTransform object. Then I've simply created a DoubleAnimation object from the button's current angle to 360 degrees. Then I've created a 'Storyboard object, added the DoubleAnimation object to its Children. But notice the next two statements. These are Storyboard static functions that set the target name for the DoubleAnimation object to "_rotateTransform" which is the name we've given the RotateTransform object with the x:Name="" notation in xaml. Then we set the target property for the DoubleAnimation object to 'new PropertyPath(RotateTransform.AngleProperty);"

If you run this application and click the button, sure enough, it rotates, translates, scales as you would expect.

It occurred to me that I don't really need to enumerate through the TransformGroup's children to find the RotateTransform object. I can call NameScope's FindName function and get the object. So I modified my 'button_Click' handler so it now looks like:

So now let's go back and remove the button_Click handler and do it all in xaml code. All we need to do is add a <Button.Triggers > element. Here is what the final xaml code looks like. Notice that we are using the same name in the storyboard's 'TargetProperty, _rotateTransform, that we defined with the x:Name="" notation.