WPF is fully capable of running a stand-alone XAML file. You simply create a XAML file similar to the following listing and view it in Internet Explorer, Kaxaml or another WPF editor.
<Page xmlns=http://...
xmlns:x=http://...>
<Canvas>
<Polyline Stroke="LightGreen"
StrokeThickness='10'
Points="330,100 160,150 100,240" /
</Canvas>
</Page>
If you want to run code from your XAML file however you have to write a .NET class. Today I want to explore the x:Class attribute and how the XAML parser, Visual Studio 2008 and you interact with this property.
Linking to .NET class
If you want to link your XAML file to a .NET class you use the x:Class attribute.
<Window x:Class="DemoApp.Demos.Blog.SimpleWindow"
You must provide a class with the same, fully qualified name as the property value or you’ll get a compiler error. In my case that means I have to have a SimpleWindow class in the DemoApp.Demos.Blog namespace. This is a basic XAML rule, and is spelled out in the MSDN documentation. To be exact the MSDN docs say:
The x:Class attribute configures XAML compilation to join partial classes between markup and code-behind. The code partial class is defined in a separate code file in a Common Language Specification (CLS) language, whereas the markup partial class is created by codegen during XAML compilation.
So what does that mean?
XAML compilation
From Rob Relyea
In WPF, we compile XAML into a combination of C# (.g.cs) or VB (.g.vb) and a special binary form (.baml). So at runtime, in most cases, there doesn’t need to be any XML parsing happening – baml is an optimized, pre-tokenized version of the elements that were specified in the .xaml file.
Hmmm. Looks like my XAML file will be compiled into two extra files.
Let’s see how this works in Visual Studio.
- Open Visual Studio and create a new WPF application
- Add a XML file. Yes, I said XML file instead of a XAML file. Why? When you add a XAML file Visual Studio always creates a second file named xxx.xaml.cs. I don’t want any extra files yet.
Compiling the XAML file
We need to add a few lines of XAML our file.
<Window x:Class="DemoApp.Demos.Blog.SimpleWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Button />
</Grid>
</Window>
Next, change the build action for the SimpleWidow.xaml to None.
Finally compile your application, open the Class View and look at the available classes. There should be a few classes, but none with the name from our x:Class attribute.
As you might have guessed setting the Compile action to Page is what causes the compiler to generate the BAML and class file. Since we changed the compile action to None we didn’t get these two files.
Change the Compile action back to Page and recompile. Now you should see a new class in the Class View.
Finding the hidden files
Obviously the compiler must have created a class named SimpleWindow for us. According to the MSDN docs there should also be a BAML file in our project. Let’s go find them.
There they are – hiding in the obj/Debug* folder – out of sight and unlikely to be changed by curious developers.
* They’ll be in the obj/Release folder if you do a Release build.
Adding your own code
SimpleWindow.g.cs is generated every time you build your application so it would be a foolish place to write your code as it would get erased with every compile. Luckily for us Microsoft used the partial keyword when generating the class in SimpleWindow.g.cs. That means we can create our own class file in our preferred location.
- Add a new Class file to the project. Give it a name of your own choosing, I picked CodeBehind.cs for the name of my class.
- In the code, put your class in a namespace and change the Class name in the code to match your x:Class attribute. For my example, that means the namespace is “DemoApp.Demos.Blog” and the class name is “SimpleWindow”. See the following example
using System;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
namespaceDemoApp.Demos.Blog
{
partial classSimpleWindow
{
public SimpleWindow()
{
InitializeComponent();
}
}
}
A couple things to point out. First, the code file and XAML have different names. The important part is that the fully qualified name of the class matches the string in the x:Class attribute. Second, I also added a constructor that calls InitializeComponent(). The InitializeComponent method is in the generated class file. A call to this method is necessary to initialize any named elements that we add to our window.
Running the Application
- We need tell the application to show our SimpleWindow on startup. Open App.xaml and modify the StartupUri as follows.
<Application x:Class=”WpfApplication1.App”
xmlns=”…”
xmlns:x=”…”
StartupUri=”SimpleWindow.xaml”>
</Application>
Run the application. You should see your SimpleWindow window.
Debrief
Now that we have a better understanding of what is going on in Visual Studio let’s look at what happens when you add a new Window or Page to your project.
Visual Studio adds two files; Window5.xaml and Window5.xaml.cs.
Window5.xaml has its build action set to Page, which causes the compiler to create the BAML and *.g.cs files in the obj folder. VS also adds the x:Class attribute to the root element.
Window5.xaml.cs: VS also write a partial class with the correct name in Window5.xaml.cs and adds a constructor that calls InitializeComponent. In other words Visual Studio automatically does everything that we’ve seen so far.
One last tip
Here’s a neat little trick for arranging your code behind classes in the Solution explorer.
- Rename CodeBehind.cs to SimpleWindow.xaml.cs.
If you look in the Solution explorer you wont see the nice nesting that the other Windows files display.
In order get this nesting behavior we need to modify the vbproj or csproj file. Open your vbproj/csproj file in a text editor (or use Unload Project in Visual Studio) and add the DependentUpon element as follows.
<Compile Include="SimpleWindow.xaml.cs" >
<DependentUpon>SimpleWindow.xaml</DependentUpon>
</Compile>
The next time you open your project you will see the little plus sign on SimpleWindow.xaml like all the other window files.
Read Full Post »