Monthly Archives: August 2015

XAML 101: Borders, Margins, and Alignment

FacebookTwitterGoogle+Share

Source code for this sample on GitHub: https://github.com/billreiss/xamlnative/tree/master/Xaml101/005_Borders_Margins_Alignment

In this post we will look at another control, and some other properties that can help us with layout. The new control for this post is the Border, and it is similar to the Grid, but it only has a single child and no rows or columns. You can think of it as a frame for another control.

Let’s modify the Grid in MainPage.xaml to look like this:

<Grid Background="Red">
    <Border Background="Cyan">
        <TextBlock Text="Border Content"/>
    </Border>
</Grid>

We have a Border with a TextBlock inside it. Running the app looks like this:

image

Notice that the Border fills the entire Grid (we don’t see any of the Red background of the Grid). This is because the HorizontalAlignment and VerticalAlignment properties default to “Stretch” to fit the container.  Changing the Border’s alignments:

<Border HorizontalAlignment="Left" VerticalAlignment="Top" Background="Cyan">
    <TextBlock Text="Border Content"/>
</Border>

Now the Border is in the upper left corner:

image

It’s really hugging the edge there. We can give it some space using the Margin property:

<Border Margin="10,10,10,10" HorizontalAlignment="Left" VerticalAlignment="Top" Background="Cyan">

And now it looks like this:

image

The Border’s Margin is set to “10,10,10,10”. These numbers represent the Left, Top, Right, and Bottom margins respectively. Note that this is a different order than margins in HTML where the order is Top, Right, Bottom, Left. We can also represent Margin as two numbers or a single number. In the case of two numbers, the Left and Right are set to the first number specified, and the Top and Bottom to the second number. If only one number is specified then all margins are set to this value. So we can change the Margin we specified above to this:

<Border Margin="10" HorizontalAlignment="Left" VerticalAlignment="Top" Background="Cyan">

If we move the Margin to the TextBlock instead of the Border, we get a slightly different look:

image

Now the background of the Border goes all the way to the edge, but the text is in the same position it was when the Margin was on the Border. There is another way to achieve this same result. We can set the Padding property on the Border:

<Border Padding="10" HorizontalAlignment="Left" VerticalAlignment="Top" Background="Cyan">

Padding is available only on some controls, where Margin is available everywhere. With Padding, it has the same effect as putting a Margin around the content contained within the Border.

Let’s consider one more type of alignment, and that is text alignment. Let’s let the Border stretch to fill the control again, and set the TextAlignment property of the TextBlock:

<Border Padding="10" Background="Cyan">
    <TextBlock TextAlignment="Center" Text="Border Content"/>
</Border>

And we get something that looks like this:

image

Now we can get a very similar effect by setting the Border or the TextBlock to HorizontalAlignment=”Center” but there is a subtle but important difference. What happens when text is too big to fit in the available space horizontally? Change the Border and TextBlock to this:

<Border Padding="10" Background="Cyan">
    <TextBlock Text="This is a very long piece of text that won't fit on the page. Are you still reading this?"/>
</Border>

Running this and shrinking down the window as small as it will go, it looks like this:

image

Notice how the text gets cut off. That’s because text wrapping on the TextBlock is off by default. We can easily fix this:

<TextBlock TextWrapping="Wrap" Text="This is a very long piece of text that won't fit on the page. Are you still reading this?"/>

Now the app wraps the text:

image

No matter how we try, and whatever HorizontalAlignments we use, the second line will always be left justified. However if we set TextAlignment to “Center” then both lines will be centered:

image

XAML 101: Grid Sizing

Source code for this sample on GitHub: https://github.com/billreiss/xamlnative/tree/master/Xaml101/004_GridSizing

In the last post we looked at Dependency Properties and a special version of those called Attached Properties. Some of the importance of these will become clearer later, but for now just treat them like you would any other property. Let’s see what other properties we can use on the powerful and flexible Grid control and its children for positioning.

In our “Hello World” app, in MainPage.xaml, we had a Grid with a couple of RowDefinitions and two TextBlocks. Let’s change things up a little to make it easier to see what is going on. Change the MainPage.xaml Grid to look like this:

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid Background="Yellow">
            <TextBlock Text="Row 0"/>
        </Grid>
        <Grid Grid.Row="1" Background="LightBlue">
            <TextBlock Text="Row 1"/>
        </Grid>
        <Grid Grid.Row="2" Background="Orange">
            <TextBlock Text="Row 2"/>
        </Grid>
        <Grid Grid.Row="3" Background="Green">
            <TextBlock Text="Row 3"/>
        </Grid>
    </Grid>

Now our Grid has 4 nested Grids inside it, and each one is in a different row, and each has a TextBlock inside it. We can nest as many Grids and other controls inside each other as we want to get the layout we desire. By setting the Background property on each of these it is easy to see the space they take up. It looks like this:
image

So we can see that these rows each take up one quarter of the available space on the page. There are 3 different types of sizing for rows (and columns) in a grid. The default is “Star” sizing, which is what we see here. A little more about that later in this post. The next sizing type is “Auto” and we can see what this does by changing the Grid.RowDefinitions as follows:

<Grid.RowDefinitions>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
</Grid.RowDefinitions>

And this is what it looks like in the running app:

image

The “Auto” size for rows sizes the row to the size of the largest element in that row. The same is true for Grid columns. Since we only have one element in each row, each row is sized to fit its content. The third type of sizing is “Pixel” sizing. Let’s change the row definitions like this:

<Grid.RowDefinitions>
    <RowDefinition Height="70"/>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
</Grid.RowDefinitions>

Now the first row will be 70 pixels high, and the other rows will size to fit their contents, like this:

image

Now back to “Star” sizing. The name “Star” comes from the asterisk that is used to show that we want to use Star sizing. The following are all equivalent:

<RowDefinition/>
<RowDefinition Height="*"/>
<RowDefinition Height="1*"/>

The default height for a row definition is “1*”, and  the “1” is implied if not specified. The number before the Star determines how much of the available space will be reserved for the row. These numbers are only important in relation to each other, if you have more than one “Star sized” row in your Grid. How it works is that “Pixel sized” and “Auto sized” are given space first, and then the remaining space is split between the “Star sized” rows. All of the numbers for “Star sized” rows are added up, and then each is given a percentage based on its value. By combining star sizes with fixed sizes (auto or pixel) you can easily create some advanced layouts such as master-detail views. Let’s see how this works. Modify the Grid.RowDefinitions as follows:

<Grid.RowDefinitions>
    <RowDefinition Height="70"/>
    <RowDefinition Height="1*"/>
    <RowDefinition Height="1*"/>
    <RowDefinition Height="2*"/>
</Grid.RowDefinitions>

And the resulting app looks like this:

image

The first row gets 70 pixels, then the next 2 rows each get 25 percent of the remaining space, and the final row gets 50 percent of the remaining space. If you prefer percentages, you can do something like this with the same result:

<Grid.RowDefinitions>
    <RowDefinition Height="70"/>
    <RowDefinition Height=".25*"/>
    <RowDefinition Height=".25*"/>
    <RowDefinition Height=".50*"/>
</Grid.RowDefinitions>

That’s it for Grid sizing basics, remember that all of these same concepts apply to Grid.ColumnDefinitions except using the Width property instead of the Height.

XAML 101: Dependency Properties and Attached Properties

Source code for this sample on GitHub: https://github.com/billreiss/xamlnative/tree/master/Xaml101/003_Dependency_Attached_Properties

This is one of those topics where it’s pretty advanced, but it’s also so fundamental to the technology that it needs to be addressed. So what we will do is talk about these Properties as they are implemented by other controls, and later we will look at how we can create our own Properties. In the last post, we set the Text property of the TextBlock. This Text property, and pretty much every other property you set on a control is actually a Dependency Property. In C#, when you create a property it’s usually something like this:

        public string Text { get; set; }

In UWP and other XAML based technologies, properties that you need to be able to access in XAML are a bit more complex. There are things like animations, data binding, triggers, setters, and more and these require notifications when the value of a property is changed. Most properties on controls are implemented as Dependency Properties. These are properties that are registered, and their values are accessed via GetValue and SetValue methods. Generally they also have simple property wrappers around these methods so that you can access them as easily as any other property. A lot more about the details of how to implement these later.

The reason I think this is important to bring up now is that there is a type of Dependency Property that is called an Attached Property. Dependency Properties are declared on a class and then are attached to another class. Dependency Properties like the TextBlock.Text property are declared on the same class that they are attached to. If a Property is declared against one class, but is attached to a different class, then this is called an Attached Property. Yes I understand that this is a little confusing, and I think an example can help. Let’s start with the HelloXaml sample from the last post. In MainPage.xaml we had this:

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock Text="Hello XAML!"/>
    </Grid>

Like I said earlier, the Text property of the TextBlock is a Dependency Property. The Background property of the Grid is too, we will talk about the strange syntax there soon. Dependency Properties in XAML can be set using XML attribute syntax (like Text and Background) but for more complex properties there is also an element syntax. Let’s consider defining two rows for our Grid control. There is a Dependency Property on Grid which is called RowDefinitions. This is how we can define two rows:

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock Text="Hello XAML!"/>
    </Grid>

Now let’s put something in the second row. This is done using the Grid.Row Attached Property.

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock Text="Hello XAML!"/>
        <TextBlock Grid.Row="1" Text="Hello Second Row!"/>
    </Grid>

The first row is row 0, so the second row is row 1. Notice the Grid.Row attached property on the second TextBlock. The Row attached property is declared on the Grid but is attached to the row, and that’s why when we use this attached property we need to say Grid.Row instead of just Row. You can actually put this prefix on any dependency property, but it’s not required. For example, instead of:

Text="Hello Second Row!"

We could say:

TextBlock.Text="Hello Second Row!"

Run this again and you will see something like this:

image

Notice how the rows are spaced and the two rows take up the same amount of space on the page. There are some other properties that can control this and in the next post we will see some of these.

XAML 101: Our First App (Part 2)

Source code for this sample is at GitHub here: https://github.com/billreiss/xamlnative/tree/master/Xaml101/002_OurFirstApp_Part2

In the last post we created a new C# Universal Windows Platform (UWP) app, ran it, and took a look at what gets generated. We also disabled the frame rate counter. Now it’s time to really get in to the XAML part of the app. MainPage.xaml contains the layout for the home page of the app. Let’s take a look.

This is what gets generated in MainPage.xaml:

<Page
    x:Class="HelloXaml.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HelloXaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    </Grid>
</Page>

So the first thing to notice are these xmlns attributes. These are XML namespaces and this is how XAML finds what it needs. Generally these map to .NET namespaces and assemblies and you can think of it similar to the “using directive” in C# (for example “using System.Collections.Generic;”),  more about these later. The “x” namespace is a special one used by XAML for internal built-in extensions. We see “x:Class”, and this is used to declare the class name for this class. This will match the namespace in the code behind in the MainPage.xaml.cs file:

namespace HelloXaml
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }
    }
}

So we have a code behind class of HelloXaml.MainPage, and we have a MainPage.xaml file with an x:Class of HelloXaml.MainPage. This links these two files together. Now a little about how the sausage is made. Even though you really don’t have to worry about this, I think it helps to know what is going on.

The MainPage.xaml file has a Build Action of “Page”. This tells Visual Studio to generate a partial class that is compiled along with MainPage.xaml.cs to create our HelloXaml.MainPage class. This generated file, named MainPage.g.i.cs has an InitializeComponent() method which is called from the MainPage constructor (see above). Any named entities (we will get to this later) will have generated code here, there is also code to load the XAML file into the object (known as deserializing or hydrating).

The root control inside the MainPage is a Grid control. You can change this if you want to, but the Grid is a pretty good choice for the root element in your page. A Grid has rows and columns (defaults to 1 row and 1 column) and you can think of it like a Table in HTML. Grid inherits from Panel, and there are a few other types that also inherit from Panel, and we will see these as we move on. The important thing about Panel (and Grid, since it inherits from Panel) is that it can have children. The various controls that inherit from Panel differ in how they treat the arrangement of their children.

Let’s add some text to the Grid. This is done with a TextBlock control. Inside the Grid, add a <TextBlock/> like this:

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock/>
    </Grid>

Now with this selected, let’s look at the Properties pane of Visual Studio. I’m a big fan of the Properties pane, especially when we get to data binding later. I like to arrange the properties By Name, but that’s up to you, whatever you prefer. When arranged by name, we can scroll down and find the Text property. Let’s set it to “Hello XAML!”. You will see in the XAML window that this change has been applied there:

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock Text="Hello XAML!"/>
    </Grid>

Run the app again, it will look something like this:

image

XAML 101: Our First App

Source code for this sample is on GitHub here: https://github.com/billreiss/xamlnative/tree/master/Xaml101/001_OurFirstApp_Part1

Let’s do the obligatory “Hello World” app and use it to show what gets generated by Visual Studio out of the box when creating a Windows 10 Universal App. Before we get started, a few things you will need:

Now in Visual Studio, select File->New Project. Under Templates->Visual C#->Windows->Universal and select Blank App (Universal Windows) and call it HelloXaml. Click OK.

image

This creates a project structure that looks something like this:

image

Run the app. You should see a blank window like this:

image

There are a lot of supporting files in the project, such as icons, configuration information, and more, and we will dig into some of these later through the course of this series. The most important files for us right now that get generated are App.xaml, App.xaml.cs, MainPage.xaml, and MainPage.xaml.cs. Here is a brief description of each of these:

App.xaml – Contains application-wide resources such as styles. Putting control styles here can keep the look and feel of your app consistent across different pages. Not much here by default except whether the app should use the light or dark theme.

image

App.xaml.cs – This is run on startup, creates the default frame for all of your app’s pages, navigates to the first page. Also handles app suspend and resume.

MainPage.xaml – The layout of the home page of your app.

MainPage.xaml.cs – The code for the home page of your app.

If you run the app in the debugger, you will see something like this in the upper left corner:

image

This is a frame rate counter, and can be useful when troubleshooting performance problems, but generally it’s just annoying. We can get rid of it pretty easily. In App.xaml.cs, at the top of the OnLaunched method, you will see the following:

#if DEBUG
            if (System.Diagnostics.Debugger.IsAttached)
            {
                this.DebugSettings.EnableFrameRateCounter = true;
            }
#endif

Let’s change this to:

#if false
            if (System.Diagnostics.Debugger.IsAttached)
            {
                this.DebugSettings.EnableFrameRateCounter = true;
            }
#endif

This way it’s easy to turn it back on again if we need it, but until then it will stay out of our way. This is a good place to stop, in the next post we will start digging in to the actual XAML of the app.

XAML 101: What is XAML Anyway?

Welcome to the first in a series of posts introducing beginners to the world of developing Windows 10 Universal Windows Platform (UWP) apps using XAML. No previous knowledge will be assumed, but some working knowledge of C# will be very helpful. I try to keep my posts lighthearted and easily accessible, we will see how I do.

XAML (or Xaml, depending on your preference, I will try to be consistent and capitalize it) was originally introduced as part of Windows Presentation Foundation (WPF) and it is a general purpose XML based format for representing any .NET object, but it is overwhelmingly used for representing layout (similar to HTML for web apps). XAML stands for eXtensible Application Markup Language (or originally eXtensible Avalon Markup Language, the code name for WPF was Avalon back in the Windows Longhorn days).  If you develop an app using XAML for Windows 10, it is generally a combination of XAML for layout and C# (or C++ or VB.NET) code for application logic. Most things you can do in XAML can also be done in code, but XAML lends itself well to design tools which can increase productivity.

XAML has come a long way in Windows 10, and a lot of the built in user interfaces in Windows 10 including the start menu, action center, settings window, Edge browser, and much more all use XAML. The Office Universal apps also use XAML. These teams are so demanding about CPU and memory performance, and the UWP SDK team had to make a lot of improvements to make their platform acceptable. We as Windows 10 app developers benefit from all these improvements and I will cover these topics as we progress through learning about XAML for Windows 10 apps.

In the next post we will create the obligatory “Hello XAML” app and start learning about this powerful app platform.

Welcome to the XAML Native Blog

This blog has been a long time coming. I originally came up with the idea before Windows 8 launched, thinking XAML would be a big part of Windows 8 apps and believing the hype that the Windows 8 Store would be a big deal. A few things happened to derail my grand design. Steven Sinofsky got on stage and said use WinJS to build your apps. Windows 8 didn’t take off the way Microsoft hoped it would (a bit of an understatement there). Windows 8 apps were harder to develop than things were on Windows Phone. Even though there were various XAML based technologies (Windows 8, Windows Phone, Silverlight, WPF, etc.) they were all different and things kept changing and shifting. We really didn’t know the future of XAML and whether Microsoft thought it was core to their strategy.

Fast forward to August 2015. Windows 10 has 75 million installs in a month. Microsoft uses XAML for a bunch of built in shell functionality and first party apps. There is a new Windows 10 Universal Windows Platform (UWP) SDK to easily build apps using XAML for Windows 10 from desktop to tablets to phone. These apps will run in a window on the desktop instead of full screen, making them a first class member of the Windows Desktop ecosystem. Let’s hope that we are finally on a stable platform where the technology can evolve instead of changing drastically with every release.

I was presenting at the Tampa Code Camp about a month ago and someone came up to me after my presentation on Windows 10 UWP apps and said “I’ve been writing applications in C# for years and just never really got a handle on XAML.” I thought about my plans to create this blog, and specifically about creating a series of posts for beginners on Developing Windows 10 apps using XAML. Not for complete beginners, I will expect that you have a working knowledge of C#, but I won’t assume any knowledge of XAML. I also plan on mixing in posts about some more advanced topics related to UWP development using XAML.

I hope you enjoy, and you can shape the direction of this blog in the comments of any of the posts. I am very excited about the future of XAML and that we can take this journey together.

Sincerely,
Bill Reiss