close
C# Online.NET Visual C# Developer Center
Search

XAML—Code-Behind Class

Visual C# Tutorials
.NET Framework Tutorials

XAML

© 2007 Matthew MacDonald

The Code-Behind Class

XAML allows you to construct a user interface, but in order to make a functioning application you need a way to connect the event handlers that have your application code. XAML makes this easy using the Class attribute that’s shown here:

1  <Window x:Class="WindowsApplication1.Window1" 

The x namespace prefix places the Class attribute in the XAML namespace, which means this is a more general part of the XAML language. In fact, the Class attribute tells the XAML parser to generate a new class with the specified name. That class derives from the class that’s named by the XML element. In other words, this example creates a new class named WindowsApplication1.Window1, which derives from the base Window class.

The Window1 class is generated automatically at compile time. But here’s where things get interesting. You can supply a piece of the Window1 class that will be merged into the automatically generated portion. The piece you specify is the perfect container for your event handling code.


Note This magic happens through the C# feature known as partial classes. Partial classes allow you to split a class into two or more separate pieces for development and fuse them together in the compiled assembly. Partial classes can be used in a variety of code management scenarios, but they’re most useful in situations like these, where your code needs to be merged with a designer-generated file.


Visual Studio helps you out by automatically creating a partial class where you can place your event handling code. For example, if you create an application named WindowsApplication1, which contains a window named Window1 (as in the previous example), Visual Studio will start you out with this basic skeleton of a class:

namespace WindowsApplication1
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
 
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
    }
}

When you compile your application, the XAML that defines your user interface (such as Window1.xaml) is translated into CLR type declaration that is merged with the logic in your code-behind class file (such as Window1.xaml.cs) to form one single unit.

Currently, the Window1 class code doesn’t include any real functionality. However, it does include one important detail—the default constructor, which calls InitializeComponent() when you create an instance of the class.


Note The InitializeComponent() method plays a key role in WPF applications. For that reason, you should never delete the InitializeComponent() call in your window’s constructor. Similarly, if you add another constructor, make sure it also calls InitializeComponent().


The InitializeComponent() method isn’t visible in your source code because it’s generated when you compile your application. Essentially, all InitializeComponent() does is call the LoadComponent() method of the System.Windows.Application class. The LoadComponent() method extracts the BAML (the compiled XAML) from your assembly and uses it to build your user interface. As it parses the BAML, it creates each control, sets its properties, and attaches any event handlers.


Note If you can’t stand the suspense, jump ahead to the end of the chapter. You’ll see the code for the automatically generated InitializeComponent() method in the section "Code and Compiled XAML".


There’s one more detail to consider. In your code-behind class, you’ll often want to manipulate controls programmatically. For example, you might want to read or change properties or attach and detach event handlers on the fly. To make this possible, the control must include a XAML Name attribute. In the previous example, the Grid control does not include a Name attribute, so you won’t be able to manipulate it in your code-behind file.

Here’s how you can attach a name to the Grid:

6      <Grid x:Name="grid1">
7      </Grid>

You can make this change by hand in the XAML document, or you can select the grid in the Visual Studio designer and set the Name property using the Properties window.

Either way, the Name attribute tells the XAML parser to add a field like this to the automatically generated portion of the Window1 class:

private System.Windows.Controls.Grid grid1;

Now you can interact with the grid in your Window1 class code by using the name grid1:

MessageBox.Show(String.Format("The grid is {0}x{1} units in size.",
  grid1.ActualWidth, grid1.ActualHeight));

This technique doesn’t add much for the simple grid example, but it becomes much more important when you need to read values in input controls such as text boxes and list boxes.

The Name property shown previously is part of the XAML language, and it’s used to help integrate your code-behind class. Somewhat confusingly, many classes define their own Name property. (One example is the base FrameworkElement class from which all WPF elements derive.) XAML parsers have a clever way of handling this. You can set either the XAML Name property (using the x: prefix) or the Name property that belongs to the actual element (by leaving out the prefix). Either way, the result is the same—the name you specify is used in the automatically generated code file and it’s used to set the Name property.

That means this markup is equivalent to what you’ve already seen:

<Grid Name="grid1">
</Grid>

This bit of magic only works if the class that includes the Name property decorates itself with the RuntimeNameProperty attribute. The RuntimeNameProperty indicates which property should be treated as the name for instances of that type. (Obviously, it’s usually the property that’s named Name.) The FrameworkElement class includes the RuntimeNameProperty attribute, so there’s no problem.


Tip In a traditional Windows Forms application, every control has a name. In a WPF application, the only elements that have names are ones that you want to manipulate programmatically. This simplifies your markup, and allows you to easily distinguish between fixed and dynamic portions of your user interface.


By now, you should have a basic understanding of how to interpret a XAML document that defines a window and how that XAML document is converted into a final compiled class (with the addition of any code you’ve written). In the next section, you’ll look at the property syntax in more detail and learn to wire up event handlers.


Previous_Page_.gif Next_Page_.gif