XAML is an XML-based markup language. Given that, it shares many properties with other XML documents, such as case sensitivity and having to be well-formed. XAML has some specific syntax peculiarities designed for easing the declaration of specific types of elements. It provides abbreviated markup syntax for specific types of elements that take advantage of the underlying Common Language Runtime (CLR) class constructors.
This chapter will examine the core XAML syntax, as well as some of the peculiarities of its abbreviated markup syntax, in preparation for understanding more complex concepts in later chapters.
Core XAML Syntax
XAML generally follows XML syntax rules, just as any other XML-based markup language does. Each XAML element has a name and one or more attributes. Attributes correspond directly to object properties, and the name of the XAML element exactly matches the name of a CLR class definition.
XAML is pure markup, which means that while the names of event handlers are specified as attributes, you must implement the actual logic of the event handler in code. If you’re familiar with ASP.NET programming techniques, then you’ll be familiar with the term codebehind , which refers to the code “behind” a XAML interface element that is responsible for providing application logic such as event handlers. It can be implemented in either C# or VB.NET. In both cases, the code can be placed inline in the XAML file, although this contradicts best practices in separating the presentation and application logic layers.
How does this work? Every event in XAML can be assigned to a codebehind handler, which is implemented in a supported .NET language. For example, it’s a common task to do something when a Button is clicked. So, first a Button is declared with the XAML code shown in Example 3-1.
Sub ButtonClickedHandler(ByVal sender As Object, ByVal eventArgs as RoutedEventArgs ) MyButton.Width = 100 MyButton.Content = "Thank you!" End Sub
In both Examples 3-2 and 3-3, the handler will change the width of the Button from 50 to 100 and change the text displayed on it from “Click Me!” to “Thank you!”. All XAML attributes can be manipulated within code because they are simply XML representations of actual CLR class attributes. You could just as easily change the button’s background color, height, and even its position in code, just as you could in a traditional Windows application.
It is also acceptable to inline code in the XAML file by specifying the <x:Code> element. All inline code must be enclosed in the <CDATA[...]]> tag to ensure that the parser does not try to interpret the code. The XAML code from Example 3-1 and the C# code from Example 3-2 yield Example 3-4.
Example 3-4. Inlining code within a XAML file (continued)
]]> </x:Code>
Application developers familiar with C# or VB.NET will immediately grasp the concept of codebehind and inline code and will be able to apply their existing skills to develop the code that drives the application.
XAML developers need to be aware that in order for application logic developers to access specific XAML elements, the elements must be named using either the Name or ID attribute. Developers will use one of these attributes to reference and manipulate the element directly from code. In Example 3-1, the Button ’s Name attribute was declared as MyButton . The same name was then used in both code examples to reference and directly access the object.
There are three basic rules to follow when declaring XAML elements:
XAML is case-sensitive. Element and attribute names must be properly cased.
All attribute values, regardless of data type, must be enclosed in double quotes.
The resulting XML must be well-formed.
The basic syntax for declaring XAML elements and attributes is:
A simple login user interface, as shown in Figure 3-1, could be described with the code in Example 3-5, which illustrates these basic rules. Note the careful atten tion to case in declaring elements and attributes, the enclosure of all attribute values (regardless of underlying data type) in double quotes, and the fact that all elements are well-formed and closed with an end tag.
Formatting is a matter of style and corporate standards. The format for the exam ples in this book was chosen because it is readable and clearly displays the nesting of elements in more complex markup. Elements can be declared all on one line, or attribute declarations can be split across lines; formatting is completely up to you. Because XAML is compiled into BAML before deployment, the amount of space taken up by elements in a XAML file is irrelevant. There are no advantages to using less space by declaring elements on a single line and no disadvantages to the formatting used in this book. The elements will become binary representations before deployment, and the whitespace will have no impact on the footprint of finished applications.
Clearly, XAML is comprised of elements and their attributes. The rest of this chapter will examine each of these concepts in depth.
All XAML elements are an XML representation of CLR classes, but not all CLR classes are represented in XAML. Most of those represented are user-interface elements and are ultimately derived from System.Windows.UIElement, which provides basic visual user-interface properties that are shared by most XAML elements. A System.Windows.UIElement can render itself, receive input via the keyboard and mouse, visually size and position its child elements, and raise events.
Not all XAML elements are derived from System.Windows.UIElement . Some, such as LineBreak , TableColumn , and Document , are derived from System.Windows.FrameworkContentElement . System.Windows.FrameworkContentElement elements cannot render themselves but are instead rendered by another class, usually the container in which they have been placed.
Most XAML elements can be organized into five basic categories:
Root elements
Control elements
Panel elements
Shape and geometric elements
Document elements
Root Elements
Root elements function as the page’s base container for all user-interface elements. A page is required to have one root element. The most commonly used root elements are the panel elements—StackPanel, DockPanel , Canvas , and Grid —and Page , a root element that allows you to declaratively control a number of the properties of the window containing the XAML page. To be considered a root element, the element must be a container for at least one other element. (When displaying XAML output in XamlPad, you don’t have to include a root element because XamlPad provides it on your behalf.) You can create custom root elements by deriving new classes from Page or Window and exposing them as XAML elements.
The root element must contain a reference to the appropriate namespace (in most cases, the default Avalon namespace, http://schemas.microsoft.com/winfx/avalon/ 2005 ). As with all XML documents, unless otherwise specified, it is assumed that all elements in the page are associated with the default namespace declared on the root element. The declaration in XAML is the same as in any XML document.
Control elements handle user interaction. Controls are interactive and allow the user to enter data, make choices, and perform other interactive tasks. They can be broken up into five categories: simple controls, content controls, item controls, header item controls, and header content controls. They are differentiated by the attributes they support, namely Content, Headers , and Items . Attribute support is determined by the underlying CLR class represented by the XAML element. Even if you don’t use the Header attribute supported by a header item control, it doesn’t become an item control because the CLR class it represents still has a Header whether or not you assign it a value. Table 3-1 summarizes this information neatly.
Simple controls
Derive directly from the System.Windows.Control class and do not have Content , Items , or Header attributes. Examples of simple controls are HorizontalScrollBar , VerticalScrollBar , Frame , TextBox , and RichTextBox .
Content controls
Have a Content attribute, but no Items or Header attributes. Content controls are restricted to only one element as its content, though that content may be an element (such as a Panel ) that can contain more than one element. Examples of content controls are Button , RepeatButton , Label , RadioButton , CheckBox , ListBoxItem , GroupItem , StatusBarItem , ToolTip , ScrollViewer , and Window .
Item controls
Have an Items attribute, but no Header or Content attributes. Item controls expose a list of elements, usually offering you a choice. Item controls include ListBox , ComboBox , Menu , ContextMenu , RadioButtonList , and TabControl .
Header item controls
Have an Items attribute and a Header attribute but no Content attribute. The Header attribute determines the label for the Items , and the Items attribute contains child elements. The Items attribute is implicitly declared as a sequence of child elements that are not assigned to it. The following declaration of a MenuItem shows how this works:
Header item controls include MenuItem and ToolBar .
Header content controls
Have a Header attribute and a Content attribute, but no Items attribute. Like a content control, the header content control may contain only one child element in its Content attribute. Header content controls include Expander and TabItem .
Table 3-1. Attributes supported by control type
Content
Header
Items
Simple
N
N
N
Content
Y
N
N
Item
N
N
Y
Header item
N
Y
Y
Header content
Y
Y
N
Please check back next week for the continuation of this article.