The XAML Markup Language

XAML stands for eXtensible Application Markup Language. It's pronounced “xammel,” rhyming with “camel.”

Most of the XAML in your applications will be produced by visual designers. However, it is sometimes necessary to edit XAML directly, and you also need to understand the role that XAML plays in your application. Consequently, in this chapter, XAML will be presented as bare markup language, with no reference to the visual designers. Chapter 13 will introduce the visual designer specifically for Window 8 XAML applications.

XAML is XML with a certain schema. You can edit it with any text editor, as long as you produce valid XAML. But like all XML, it's tedious to edit, which is why you'll want to use visual designers whenever possible.

There's nothing magical about XAML. Anything that's possible in XAML is also possible in code, though the XAML is often more compact and easier to understand.

Strictly speaking, XAML isn't just for user interfaces. Windows Workflow uses XAML to describe workflows, for example. However, for simplicity in this book, XAML will be discussed solely as a user interface technology.

A Sample Page of XAML

A page of XAML describes a set of instances of .NET classes. It includes property settings for those classes, and how the classes are grouped together. The grouping takes the form of a logical tree. There is a root element, which contains other elements. Those elements may then contain sub-elements, and so on.

Here's an example to illustrate the idea. This is real, valid XAML, though for a very simple and pointless user interface (code file: FirstExample.xaml):

<UserControl x:Class="SampleUC"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300" >
    <Border BorderThickness="4" BorderBrush="Blue">
        <StackPanel>
            <Button Margin="5">I'm a button</Button>
            <Image Margin="5" Source="http://billyhollis.com/TextureWavy.jpg" />
            <TextBox Margin="5">Text for editing</TextBox>
        </StackPanel>
    </Border>
</UserControl>

The first line tells us that the root element you are using is a UserControl. Almost any XAML element can be a root element, but normally the root is a container for holding other elements. Page, Window, and UserControl are common root elements.

The declaration of the UserControl element includes several XML attributes. Some of them are simple property settings, such as the Height and Width of the UserControl. Others are more complex, and declare XML namespaces. These namespaces refer to the assemblies that contain the elements references in the rest of the XAML page. At first, you won't have to worry about these, because the designers will be inserting and managing them for you. The previous page, in fact, was generated by the Visual Studio designer.

This chapter assumes that you have a minimal understanding of XML, at least to the point of understanding the difference between an XML element and an XML attribute, and what an XML namespace is. If that's not true for you, then you should gain some exposure to XML basics before working with XAML.

After the UserControl element's declaration, the next element is a Border. This visual element illustrates a basic principle about XAML. Each visual element normally has a narrow functionality set. The Border element only knows how to draw a border. It doesn't know how to scroll, for example; a different element is needed for that, called ScrollViewer.

The Border also doesn't know how to arrange other elements. In fact, it can have only a single child. However, that child can be a type of container that does know how to arrange multiple elements. In this case, the Border contains a StackPanel.

The StackPanel can be a container for other elements such as buttons and text boxes. StackPanel's narrow responsibility is just to stack its child elements. (By default, the stacking is vertical.) StackPanel doesn't have any capability, for example, to draw a border around itself. It must depend on a Border element for that.

The subelements of the StackPanel declare the visual elements that will be stacked inside the StackPanel. In our example, there are three: a Button, an Image, and a TextBox.

If you place the previous XAML in an application, you can get a visual surface based on it, which would look something like Figure 12.1.

Figure 12.1 The sample page of XAML, rendered in Windows 8 (left) and WPF in Windows 7 (right)

12.1

As the screens in Figure 12.1 indicate, there are some significant differences in the way XAML is rendered on the different platforms. Sometimes defaults are different, as you see in the different default backgrounds. Varying defaults may even affect sizing, as seen in the differing Button elements. In Windows 8 XAML, the Button is left aligned by default, but it is stretched by default in WPF.

Code Behind and Naming of Elements

XAML describes object instances, and sometimes those objects generate events which must be handled. Suppose, for example, the Button defined in the XAML you saw earlier needs to cause some code to run when the Button is clicked.

Visual Studio allows you to enter such code by double-clicking the Button in the visual designer. XAML also allows hookup of event handler via an XAML attribute. Here is a line of XAML from the earlier example, with the addition of an event handler for the button.

<Button Margin="5" Click="Button_Click"> >I'm a button</Button>

The code in a code-behind module must have some way to identity a XAML element before it can work with that element. That identification is usually done with a Name property, just as it is in other designers.

Naming an element in XAML is not required unless you want to reference the element in code. In the first example of XAML discussed previously, none of the elements had a name.

You can name most elements in XAML using a Name attribute, which sets the Name property on the element. All routine controls and containers have a Name property.

Some elements do not have a name property. XAML provides a special way to reference those elements in code: the x:Name attribute. x:Name works just like the Name property for the purposes of referring to an element in code, but it is available for any element, whether or not it has a Name property.

Getting Our Terminology Straight

In most user interface technologies, the word control is used generically to refer to just about anything you might place on a visual design surface. In XAML, the word control has a more restrictive meaning. A control in XAML is a visual element that is designed with user input in mind. A TextBox, for example, clearly fits that meaning. A StackPanel does not.

Containers such as StackPanels are generically referred to as panels rather than controls. Controls and panels do not exhaust the possibilities; the Border element shown in the earlier example is in a category called decorators.

The generic word for a XAML visual object is an element. That's reflected in the base classes for visual elements, which have names like UIElement and FrameworkElement. Panels, controls, and decorators, then, are all different categories of elements.

The UIElement and FrameworkElement Classes

The UIElement base class for visual XAML elements implements functionality needed by all elements, such as input via the keyboard, mouse, touch, and stylus. The FrameworkElement base class inherits from UIElement and adds layout capabilities, data binding, and styling. For routine application development, you will not need to know anything more about these classes.

You will use the FrameworkElement type on occasion. For example, the children of a panel are a collection of FrameworkElement instances. To loop through such a collection, you'll need an index variable of type FrameworkElement.

Commonly Used Elements

All XAML platforms support some commonly used elements. Two panels are always available: StackPanel and Grid. Several standard controls are included in all three, including Button, TextBox, Image, Slider, CheckBox, and RadioButton. TextBlock is available in all three platforms for display of text. Border and ScrollViewer are used on all three platforms for drawing borders and scrolling text.

There are other elements that are included in all three platforms, but each platform also has specific elements that other platforms do not have. You'll look at several of the elements specific to Windows 8 in the next chapter.

Property Setting: Attribute Syntax vs. Element Syntax

As mentioned in the very first description of XAML, visual elements can have properties set via XML attributes. Here's another example:

<StackPanel Width="150" Background="Blue">

There is sometimes more going on with such a property setting than meets the eye. Setting the Width property to 150 units is straightforward. However, setting the Background property in this case requires more work under the covers. The setting of “Blue” is transformed by the XAML parser into an element called a SolidColorBrush. That element has a property that holds a color, and the color is set to blue.

There is another way to set a property value besides using an attribute. It's done using a specially constructed XML element. Here is another XAML example, and it yields exactly the same results as the one immediately previous one:

 <StackPanel Width="150">
    <StackPanel.Background>Blue</StackPanel.Background>

In this case the property value of Blue is between two element tags, one starting and one ending. The element tag is constructed from the class name and the property name.

All properties can be set this way. Normally, attributes are used because the XAML is more concise and easier to read. However, sometimes the alternative element-based syntax is needed because an attribute value cannot be used for the desired property value.

For example, the Background property can be set to other types of brushes. (The “Brushes” section to come covers basics on brushes.) One example is a linear gradient brush.

There is no simple string to set the Background to a linear gradient brush. It requires several lines of XAML to do it. Element-based syntax creates a “hole” in the XAML, so to speak, that provides a place to put such additional XAML. Let's see what the previous example of setting the Background property looks like when it is set to a linear gradient brush:

<StackPanel Width="150">
    <StackPanel.Background>
        <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
            <GradientStop Color="Black" Offset="0" />
            <GradientStop Color="White" Offset="1" />
        </LinearGradientBrush>
    </StackPanel.Background>

Don't worry at this point about the detailed syntax of LinearGradientBrush; the visual designers usually write that XAML for you. The point is that the XAML is complex enough that it can't be placed in an attribute. Element-based syntax is a necessity to set the value of the Background property to a LinearGradientBrush.

You must become comfortable switching between attribute-based and element-based syntax in XAML as necessary. In many cases, what begins as a simple attribute-based property must later be changes to a more complex value that requires element-based syntax.

Referencing Additional Namespaces in XAM

As mentioned earlier, the capability to reference a namespace with “xmlns” is a part of the XML standard. You can think of these namespace definitions as similar in concept to specifying an Imports statement in Visual Basic or a using statement in C#.

The first example only showed two namespaces:

<UserControl x:Class="SampleUC"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

The first namespace is the default XML namespace, and it contains elements that can be used without a prefix, such as <Button>. The second namespace includes some helper objects; the x:Name attribute discussed previously is from that namespace.

Only one default namespace can exist per XML page. All other namespaces defined in the XML page must have an identifier. The second namespace has such an identifier.

You can add your own namespace definitions to a XAML page to reference other classes. There are several situations in which you might need to do this. If you are using third-party controls, for example, those controls will be in their own namespace, and that namespace will need to be referenced in any XAML page that uses the controls. If you drag third-party controls out of the toolbox, the visual designer may insert additional namespace references into the XAML page for you, but if you are hand-coding those controls into the XAML, you may have to specify the namespace references manually.

If you write your own classes that are used in XAML, you will also need to add a namespace reference to your XAML pages to use those classes. You'll see an example later in this chapter: value converters, which translate property values during the binding process.

Namespace references in XAML don't have to use the URI tag approach. The xmlns definition can directly reference the assembly by name.

The different XAML platforms have slightly different syntax for such namespace references. If your local project assembly were named MyXAMLApp, in WPF or Silverlight, declaring a namespace for the local assembly would be done like this:

xmlns:local="clr-namespace:MyXAMLApp "

In Windows 8 XAML, the syntax is slightly different:

xmlns:local="using:MyXAMLApp "

The XAML editor in Visual Studio offers a drop-down to help you create your namespace declarations, so you don't need to memorize this syntax.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset