Chapter 2. Understanding XAML

What You’ll Learn in This Hour:

XAML, or Extensible Application Markup Language, is an XML-based language created by Microsoft. It’s as fundamental to WPF as HTML is to web development.

What Is XAML?

XAML (pronounced zammel) is the language used for creating user interfaces in WPF. It’s an XML-based markup language similar to HTML, MXML, or XUL. XAML has applicability well beyond defining user interfaces. In fact, it’s even possible to represent data with XAML, such as an array of strings or an instance of object. XAML is also used by Windows Workflow Foundation (WF) for defining workflows. In the most general sense, XAML is a language for serializing .NET object instances into a human readable format.

Even though Visual Studio 2008 provides a WYSIWYG editor with drag-and-drop support for producing and manipulating XAML, you will often need to edit your markup directly. We’ll be writing our XAML by hand for most of the book. The default file extension is .xaml.

XAML can be either compiled or interpreted, depending on how it is used. Some features, such as embedding C# or VB code in XAML, work only when the XAML is compiled. When you create a WPF application with Visual Studio, the XAML used in the application is compiled into the resulting executable. However, you can create .xaml files that are meant to be interpreted on-the-fly (no compilation is involved). These XAML files are usually hosted in a web browser.

Let’s create a simple “hello world” XAML application. You’ll need to have the .NET Framework 3.5 installed to do this exercise. It’s installed as part of Visual Studio 2008.

  1. Open your favorite text editor, such as Notepad.

  2. Create a plain text document and enter the following:

    <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
      <TextBlock Text="Hello World!" />
    </Page>
  3. Save the text file and name it HelloWorld.xaml.

  4. Double-click the newly created file, and it should open in a web browser. If another application has been mapped to .xaml, you will need to launch the browser first (either Internet Explorer 7 or Firefox will do) and drag the file into the browser.

Congratulations, you’ve just created your first WPF application using XAML. HelloWorld.xaml is an example of interpreted XAML because we never compiled the application to an executable. XAML-only applications are rather limited, and in real life you’re much more likely to use XAML in concert with C# or VB.

In HelloWorld.xaml, notice that the root element is a Page tag. Some other possibilities exist, most frequently the Window tag, but we’ll get to that shortly. When authoring XAML, your root element always defines two namespaces. The default namespace is specifically mapped to WPF, whereas the prefix x: is for XAML’s more generic features. Remember, XAML can be used to represent all kinds of data; we used the default namespace to say that we are representing data about WPF. The x namespace is representing a broader context. That may sound a little backward, but you’ll quickly find that you don’t use the x namespace as much as the default one. If this doesn’t make sense, don’t worry about it for the moment. It won’t stop you from using XAML, and we’ll review it again later. Just know that these namespace aliases are the convention adopted by Microsoft, and you’ll see it in all the examples and documentation.

By the Way

Namespaces in XML are often confusing if you have not worked with them before. Namespaces in XML serve the same function as namespaces in .NET; they provide a scope for unique names.

It’s similar to the idea of having two people named John Smith. To distinguish between them, you might call one John Smith from Surrey and the other John Smith of Boston. Including the place where they are from is analogous to the namespace. When two things are named the same, and we can’t tell them apart, it is called a naming collision.

The xmlns attribute is used to map a local name (or alias), such as x, to the actual namespace, which is specified as a URI. Individual elements or tags that reside in the namespace use the local name as a prefix in their tags.

The namespace tells the XML parser how the elements in the document should be interpreted.

The Syntax of XAML

As a general rule, an element in XAML is an instance of an object and attributes are properties on that object. The markup in Listing 2.1 is for a simple button on a page.

Example 2.1. A Simple Button in XAML

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Button x:Name="blueButton"
          Width="100"
          Height="40"
          Background="Blue"
          Content="Click Me" />
</Page>

The root element corresponds to an instance of Page, more specifically System.Windows.Controls.Page. Page, and everything else in the System.Windows.Controls namespace, is a WPF control.

The Button element corresponds to an instance of the class System.Windows.Controls.Button. In turn, the attributes on the Button element represent properties on an object instance. Thus, we are setting the values for the properties of Width, Height, Background, and Content.

There is also the x:Name attribute, which breaks the rule here. x:Name is not a property on the Button class. Instead, it’s a special attribute that provides a unique identifier to the object for accessing it in code. It is the same as creating a variable of type Button with the name blueButton. The Button element in the preceding XAML is equivalent to the following C#:

Button blueButton = new Button();
blueButton.Width = 100;
blueButton.Height = 40;
blueButton.Content = "Click Me";
blueButton.Background = new SolidColorBrush(Colors.Blue);

The Background property is a little more complex than the others. We’ll talk about that in a second. It is important to understand that any XAML element you want to reference, in code or elsewhere in the XAML, must have a unique value for x:Name. Providing a value from x:Name is like creating a variable and then setting the variable to the instance of the object.

By the Way

The Button class has a Name property, and interestingly enough, setting a value for x:Name also sets the same value for Name. In fact, for any object that has a Name property, the two attributes can be used interchangeably. This was very confusing for us when we first started working with XAML.

It’s pretty easy to get into trouble using the Name property, though, and unless you have a specific need, we recommend sticking with x:Name. It’s the convention that is generally adopted.

Setting Properties That Aren’t Simple Types

On the Button class, Width and Height are simple value types. WPF converts the string value 100 to a double implicitly. However, many properties on controls are not simple value types. Some properties are objects that have lots of properties themselves, which could also be complex types. In our example, the Background property on Button is of type Brush. In the XAML, we are able to simply say Blue and it works.

There are many places in XAML where commonly used types, such as SolidColorBrush, can be represented by a simple string value that WPF just knows how to handle. In the case of SolidColorBrush, you can provide any named color, as found on the System.Windows.Media.Colors class, or you can provide a hexadecimal representation of the color similar to those you would use in HTML or CSS. Both of the following XAML snippets are equivalent:

<Button Background="#FF0000FF" />
<Button Background="Blue" />

In some situations, however, this shorthand is not sufficient for telling WPF what you want. In those cases we can use property element syntax. Property element syntax is an alternative syntax used for providing values for complex types. Instead of setting the Background property using an attribute, we can use a child element. The following snippet demonstrates using this alternative syntax for setting the background to blue:

    <Button>
        <Button.Background>
            <SolidColorBrush Color="Blue" />
        </Button.Background>
    </Button>

The child element is referred to as a property element. Property elements take the form of <ClassName.PropertyName />. That is, the first part of the element’s name is the class name, followed by a dot, followed by the property’s name. The content of the child element is the value we want to set. When using a property element, we need to be more explicit and tell WPF that we want the value to be an instance of SolidColorBrush with the Color property set to blue. This syntax can become very verbose, but in many situations it is the only way to provide the exact value that you desire.

It’s preferable to use the shorthand when possible. Succinct markup is easier to read and it makes the intention of the XAML clearer.

The Content Property

Many of the WPF controls that you will encounter have a property named Content. Content is a special property. In Listing 2.1, we set the Content of a Button to a string value, Click Me. However, you can also set the Content property implicitly using a child element. For example, the following XAML elements are equivalent:

<Button Content="Click Me" />
<Button>Click Me</Button>

Both buttons will be rendered the same in WPF. What’s exciting is that Content is actually of type object. That means that we can make a button’s content much more than just a simple string. For example, perhaps we want to draw a yellow circle inside our button. You could use the following XAML:

    <Button>
        <Ellipse Width="24"
                 Height="24"
                 Fill="Yellow" />
    </Button>

You can always set the Content property explicitly, too:

    <Button>
        <Button.Content>
            <Ellipse Width="24"
                     Height="24"
                     Fill="Yellow" />
            </Button.Content>
    </Button>

However, doing so is more verbose and does nothing to improve the readability or maintainability of your code. Furthermore, the convention of setting the Content property implicitly is almost universally adopted.

If you go back to Listing 2.1 one more time, you will notice that our Button element is actually the value for the Page.Content property.

Markup Extensions

Sometimes we need to specify values in our markup that are either difficult to express in XAML or outside the scope of the XAML processor. XAML has a feature called markup extensions and it allows us to handle these awkward situations.

For example, suppose we have a specific color we want to use as the background for several buttons in a WPF application. We could set the Background property on each of the buttons to use the same color, but it would become tedious if we ever needed to change that color. With WPF, we can store the color with a lookup key in an application’s resources. (We’ll discuss this concept in depth in Hour 14, “Resources and Styles.”) Now we can set the background of the buttons to the color we stored in the resources. If we want to change the color, we need do so in only one place. That’s a lovely scenario, but how would we handle this in XAML? We would use a markup extension.

In the preceding scenario, the XAML with the markup extension might look like this:

        <Button Background="{StaticResource ResourceKey=myColor}"
                Content="Click Me" />

Markup extensions are indentified by the presence of curly brackets ({}). The first word in the markup extension tells WPF what kind of extension it is. The name of the extension is optionally followed by a set of named parameters. In this case, the extension is for retrieving a shared resource from a library of resources. The name of the extension is StaticResource, and we provide a value of myColor for the ResourceKey parameter. Many extensions have a default parameter. You don’t have to explicitly reference a default parameter. You are allowed to omit the parameter name and the equal sign. For example, we could restate the snippet without ResourceKey=:

       <Button Background="{StaticResource myColor}"
               Content="Click Me" />

ResourceKey is the default parameter for StaticResource.

In some cases, you will have more than one parameter. If you do, you must separate name/value pairs with commas. The general pattern is this:

{ExtensionName Param1=Value1, Param2=Value2, Param3=Value3}

The most frequent mistake in dealing with markup extensions is to include quotation marks around the values. You are not allowed to have quotation marks between the curly brackets. This confuses the parser. It also means that parameter values cannot have whitespace.

Many markup extensions are built in to WPF, and you can even write your own (however, it is not common to do so).

We’ll cover specific extensions as they become relevant throughout the book; however, Table 2.1 has a very brief summary of the most significant extensions. Don’t be too concerned about understanding these extensions right now; they will make sense in context.

Table 2.1. Common Markup Extensions in WPF

Name

Description

Binding

The extension used for binding data. This is discussed in Hour 6, “Introducing Data Binding.”

StaticResource

This is used for retrieving data from an application’s resources. Static resources are not expected to change while the application is running. We cover this in Hour 14.

DynamicResource

Similar to StaticResource, except that the data in the resource might change during runtime. This is also in Hour 14.

x:Null

Used for specifying a null value in XAML. We’ll show one way to use this in Hour 23, “Animation,” although it has many uses.

x:Type

This extension is used for supplying a System.Type object. This is also in Hour 14.

X:Array

This allows you to define an array of objects in XAML. We’ll demonstrate the use of this in Hour 15, “Digging Deeper into Data Binding.”

Summary

Understanding XAML is essential to working with WPF. Although it is possible to write a WPF application without XAML, it is awkward and clumsy. XAML is very flexible, and a lot of traditional programming tasks can now be handled with XAML. Like WPF in general, you won’t be able to master XAML overnight. Even developers who have worked with the language for some time often discover features they were unaware of.

The goal of this hour was to equip you with a foundational knowledge of XAML and how it is used. We will continue to build on that foundation in the remaining hours.

Q&A

Q.

Why are attributes in these examples often placed on new lines by themselves? Is that a requirement of XAML?

A.

No, it is not a requirement. For the most part, XAML is unconcerned about the whitespace. There is a growing trend of placing the secondary and following attributes on a new line, indenting to align with the first attribute. We adopted this convention for the book because it promotes the readability of the XAML.

Q.

I’ve heard about object element syntax in regard to XAML; how does that fit in with what we have discussed?

A.

Object element syntax is the name for declaring objects in XAML. Its name comes from the fact that an XML element in XAML corresponds to an instance of an object in .NET.

Q.

If powerful WYSIWYG editors exist for XAML, why should I bother learning all the details of the language?

A.

WYSIWYG editors are excellent tools for getting work done quickly; however, they don’t always produce the most efficient XAML for your specific application. Additionally, there are many tasks that the editors do not support. You’ll also find that some things are just easier to handle manually. Finally, a thorough understanding of XAML and how it relates to WPF provides a solid base for building efficient and effective WPF applications.

Workshop

Quiz

1.

What is the purpose of the x:Name attribute in XAML?

2.

What is a feature of XAML that is available when it is compiled rather than interpreted?

3.

Can you identify the syntactical mistake in the following markup extension?

{StaticResource ResourceKey="myData"}

Answers

1.

The x:Name attribute allows you to uniquely identify an instance of an object defined in XAML. The value of the x:Name attribute can be referenced in the associated C# or VB code.

2.

When your XAML is compiled, you can embed procedural code such as C# or VB. For more information about this, look up the markup extension x:Code.

3.

Quotation marks are not needed when specifying values in a markup extension. In fact, using quotation marks will confuse the XAML processor.

 

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

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