Sdílet prostřednictvím


Quickstart: Create a UI with XAML (XAML)

[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]

When you choose to develop your app in Microsoft Visual Basic, C#, or Visual C++ component extensions (C++/CX), you use XAML to define the user interface. XAML is a declarative language that you can use to create application UI such as controls, shapes, text, and other content presented on the screen. If you're familiar with web programming, you can think of XAML as similar to HTML. Like HTML, XAML is made up of elements and attributes. But XAML is XML-based and therefore must follow XML rules, which include being well-formed. You might ask, "Why do I care about XAML if I'm just going to use tools like Microsoft Visual Studio or Blend for Visual Studio to create the UI?" Even though there are tools that generate markup, you'll invariably want to go under the covers to understand or tweak the XAML. Besides, sometimes it's just easier to code UI by hand when you want fine control or just want to know what's going on.

Roadmap: How does this topic relate to others? See:

Prerequisites

We assume that you can create a basic Windows Runtime app using Visual Basic, C#, or C++. For instructions on creating your first Windows Runtime app, see Building your first Windows Store app using C#, C++, or Visual Basic.

XAML example

Here is a simple XAML example that creates a button.

<Grid Margin="12,0,12,0">
    <Button Content="Click Me"/>
</Grid>

Use the <Button> element to specify the Button control. Let the button size itself dynamically when you can, or use the Width and Height attributes to specify an exact size when necessary. The <Grid> is generated when you create a new Windows Runtime app using C++, C#, or Visual Basic app in Visual Studio, and is used to lay out objects. To learn more about XAML layout, see Quickstart: Defining layouts.

You can use Visual Studio to generate the XAML. For example, you can drag a button from the Toolbox to the design surface, or double-click Button in the Toolbox.

Here's the XAML that Visual Studio might generate.

<Grid>
    <Button Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top"/>
</Grid>

Visual Studio adds some extra attributes, such as HorizontalAlignment and sometimes Margin, to position the button. You might not want this extra markup if your needs are very specific or if you plan to do some redesigning later. If so, just delete the attribute.

One aspect of using a declarative language like XAML is having some separation between the markup that makes up the UI and the code that makes the application do something. For example, a designer on your team could design a UI and then hand off the XAML to the developer to add the procedural code. Even if the designer and the developer are the same person (as they often are), you can keep your visuals in XAML files (.xaml) and your procedural UI code in code-behind files (.cs and .vb).

XAML is just procedural code (only easier)

XAML elements, such as <Button />, are the equivalent of instantiating objects in procedural code. For example, consider this XAML.

<Grid x:Name="ContentPanel" Margin="12,0,12,0">
    <Button Height="72" Width="160" Content="Click Me" />
</Grid>

The following shows how this XAML could be partially replaced by code written in C# or Visual Basic.

// Initialize the button
Button myButton = new Button();
// Set its properties
myButton.Width = 160;
myButton.Height = 72;
myButton.Content = "Click Me";
// Attach it to the visual tree, specifically as a child of
// a Grid object (named 'ContentPanel') that already exists. In other words, position
// the button in the UI.
ContentPanel.Children.Add(myButton);
' Initialize the button
Dim myButton As New Button()
' Set its properties
myButton.Width = 160
myButton.Height = 72
myButton.Content = "Click Me"
' Attach it to the visual tree, specifically as a child of
' a Grid object (named ContentPanel) that already exists. In other words, position
' the button in the UI.
ContentPanel.Children.Add(myButton)
// Initialize the button
    Button^ myButton = ref new Button();
    // Set its properties
    myButton->Width = 160;
    myButton->Height = 72;
    myButton->Content = "Click Me";
    // Attach it to the visual tree, specifically as a child of
    // a Grid object (named 'ContentPanel') that already exists. In other words, position
    // the button in the UI.
    ContentPanel->Children->Append(myButton);

For UI, XAML is easier to read and more compact than procedural code. But in rare cases it's necessary to use procedural code to create UI dynamically.

Properties

There are two ways to specify property values in XAML.

  • Attribute syntax
  • Property element syntax

Attribute syntax is the attribute="value" syntax that you saw in the earlier examples and that you might be familiar with from HTML. In the next example, we create a red Rectangle. We set the Fill attribute to a predefined color name, which the XAML parser converts into a SolidColorBrush appropriate for the Fill property.

<Rectangle Fill="Red" />

Alternatively, you could specify the color value by using property element syntax.

<Rectangle>
    <Rectangle.Fill>
        <SolidColorBrush Color="Red"/>
    </Rectangle.Fill>
</Rectangle>

In this case, you explicitly specify the SolidColorBrush object that is the type the Fill property requires, rather than just using the string "Red". From this example, you might deduce that property element syntax is just a verbose way to do the same thing. But not all property values can be specified by using a simple attribute string. Not all types have type converters from strings. Plus, if you need to specify multiple properties of an object used as the value of a property, you'll likely need to use property element syntax. This example creates a Rectangle, but instead of a simple red fill, it uses a gradient created by a LinearGradientBrush.

<!-- This rectangle is painted with a diagonal linear gradient. -->
<Rectangle Width="200" Height="200">
    <Rectangle.Fill>
        <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
            <GradientStop Color="Yellow" Offset="0.0" />
            <GradientStop Color="Red" Offset="0.25" />
            <GradientStop Color="Blue" Offset="0.75" />
            <GradientStop Color="LimeGreen" Offset="1.0" />
        </LinearGradientBrush> 
    </Rectangle.Fill>
</Rectangle>

The Fill property uses a complex object, LinearGradientBrush, to create the gradient. In cases like these, you must use the property element syntax rather than simply specifying the value as a string assigned to an attribute.

XAML and the visual tree

In XAML, you have elements, such as <Button> and <Grid>, that can have other elements (nodes) underneath them (children). This parent/child relationship specifies things like how objects are positioned on the screen and how they respond to user-initiated events. Consider this example.

<Grid x:Name="ContentPanel" Background="Red" Grid.Row="1" Margin="12,0,12,0">
    <StackPanel Margin="20" Background="Blue">
        <TextBlock x:Name="firstTextBlock" FontSize="30">First TextBlock</TextBlock>
        <TextBlock x:Name="secondTextBlock" FontSize="30">Second TextBlock</TextBlock>
        <TextBlock x:Name="thirdTextBlock" FontSize="30">Third TextBlock</TextBlock>
    </StackPanel>
</Grid>

The blue StackPanel is contained within a red Grid. The TextBlock elements are contained within the StackPanel (these TextBlock elements are children of StackPanel). In addition, the TextBlock elements are stacked on top of one another in the order they are declared in XAML.

This tree diagram shows the relationships among elements.

Besides determining how content is presented, the visual tree also can have an effect on how events are processed. Many events that are related to UI and input bubble events up the tree. For example, you can attach an event handler to the StackPanel that handles when a user presses/clicks any of the TextBlock objects. Here's how to add a PointerPressed event handler named "commonHandler" to the StackPanel from the diagram.

<Grid Background="Red" x:Name="ContentPanel" Margin="12,0,12,0">
    <StackPanel Margin="20" Background="Blue" PointerPressed="commonHandler">
        <TextBlock x:Name="firstTextBlock" FontSize="30" >First TextBlock</TextBlock>
        <TextBlock x:Name="secondTextBlock" FontSize="30" >Second TextBlock</TextBlock>
        <TextBlock x:Name="thirdTextBlock" FontSize="30" >Third TextBlock</TextBlock>
    </StackPanel>
</Grid>

Here's the procedural code to handle the event.

private void commonHandler(object sender, PointerRoutedEventArgs e)
{
FrameworkElement feSource = e.OriginalSource as FrameworkElement;
switch (feSource.Name)
{
    case "firstTextBlock":
        firstTextBlock.Text = firstTextBlock.Text + " Click!";
        break;
    case "secondTextBlock":
        secondTextBlock.Text = secondTextBlock.Text + " Click!";
        break;
    case "thirdTextBlock":
        thirdTextBlock.Text = thirdTextBlock.Text + " Click!";
        break;
    }
}
Private Sub commonHandler(sender As Object, e As PointerRoutedEventArgs)
    Dim feSource As FrameworkElement = e.OriginalSource
    Select Case feSource.Name
        Case "firstTextBlock"
            firstTextBlock.Text = firstTextBlock.Text & " Click!"
        Case "secondTextBlock"
            secondTextBlock.Text = secondTextBlock.Text & " Click!"
        Case "thirdTextBlock"
            thirdTextBlock.Text = thirdTextBlock.Text & " Click!"
    End Select
End Sub
//BlankPage.xaml.h
virtual void CommonHandler(Platform::Object^  sender, 
                    Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e);

//BlankPage.xaml.cpp
void BlankPage::CommonHandler(Platform::Object^  sender, 
                    Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e)
{
    FrameworkElement^ feSource = safe_cast<FrameworkElement^>(e->OriginalSource);

    if (feSource->Name == "firstTextBlock")
    {
        firstTextBlock->Text = firstTextBlock->Text + " Click!";
    }
    else if (feSource->Name == "secondTextBlock")
    {
        secondTextBlock->Text = secondTextBlock->Text + " Click!"; 
    }
    else if(feSource->Name == "thirdTextBlock")
    { 
        thirdTextBlock->Text = thirdTextBlock->Text + " Click!"; 
    }  
}

When you run this example and you click/press a TextBlock, the event gets captured by the TextBlock, but then the event bubbles up to its parent element (the StackPanel), which then handles the event.

This diagram shows how the event bubbles up the tree.

Because the event continues up the tree, you could listen for the PointerPressed event in the Grid element too.

For more info on routed events and how to write handlers, see Events and routed events overview.

A quick guide to XAML attributes and markup extensions

When you either produce or examine XAML in an editor after producing it with Visual Studio design tools, you often use certain markup concepts that are unique to XAML, and are not directly represented in the backing programming language. Here is a list of some of these concepts.

  • The x:Name attribute. Add this attribute on any XAML object element where you want to be able to reference the created runtime instance as part of your code-behind logic. The string you specify for x:Name becomes the name of the created instance from within partial classes that are correlated with your XAML, and you can reference the instance by using that name. Visual Studio or Blend for Visual Studio often add x:Name to the XAML automatically.
  • The x:Key attribute. Add this attribute on XAML object elements in one particular circumstance: when you are defining the resources that are contained in a XAML ResourceDictionary. For more info see ResourceDictionary and XAML resource references.
  • The x: in both x:Key and x:Name identifies that these entities are defined by the XAML namespace for the XAML language itself. This is what enables these attributes to be applied to just about any XAML object element, including elements that represent classes you defined yourself.
  • {Binding} is a XAML markup extension that you use to establish a data binding reference in XAML. For more info about data binding concepts, see Quickstart: Data binding to controls or Data binding overview.
  • {TemplateBinding} is a specialized form of a binding declaration that connects the properties of a template with the runtime properties of the class that applies the template. RelativeSource is a related markup extension that can set the {RelativeSource} property of a binding in markup.
  • {StaticResource} is a markup extension that you use to reference any of the XAML-defined resources in a XAML ResourceDictionary. {StaticResource} takes a single argument, which specifies the same key string as the x:Key that you used to identify the resource in the ResourceDictionary.
  • If you ever need to specify a null value in XAML, use the string {x:Null}.

For more info, see Basic XAML syntax guideXAML namespace (x:) language features or Windows Runtime namespace extensions for XAML

Roadmap for Windows Runtime apps using C# or Visual Basic

ResourceDictionary and XAML resource references

XAML overview

Basic XAML syntax guide