Tag Archives: XAML101

XAML 101: All Samples Now on GitHub

FacebookTwitterGoogle+Share

I just wanted to let everyone know that I have gone back through all of the XAML 101 series of posts and created projects on GitHub for each of them, and will continue adding samples to GitHub for future posts, as well as keeping older samples up to date as new versions of the UWP SDK are released. You can find the GitHub repository here:

https://github.com/billreiss/xamlnative/tree/master/Xaml101

More posts soon!

XAML 101: Two Way Data Binding

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

In the last couple of posts we looked at getting started with data binding and then some more options available. In all of these cases the data binding was from the source to the target, or the model to the view, but we haven’t looked at sending data the other way through the binding. Let’s look at that now.

Where you would need two way data binding is when you aren’t in read only mode for your view and you want to edit the data. It could be a text box, a check box, a combo box, a selected item in a list, or one of many other ways to provide input. Let’s look at a couple of these. In MainPage.xaml we will have the following, a lot of it we have already seen, and a couple of new controls:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.RowDefinitions>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="auto"/>
        <ColumnDefinition Width="200"/>
    </Grid.ColumnDefinitions>
    <TextBlock Text="Checkbox:"/>
    <TextBlock Grid.Row="1" Text="Checkbox Result:"/>
    <TextBlock Grid.Row="2" Text="TextBox:"/>
    <TextBlock Grid.Row="3" Text="TextBox Result:"/>
    <CheckBox Grid.Row="0" Grid.Column="1" IsChecked="{x:Bind Model.CheckBoxValue,Mode=TwoWay}"/>
    <TextBlock Grid.Row="1" Grid.Column="1" Text="{x:Bind Model.CheckBoxValue, Mode=OneWay}"/>
    <TextBox Grid.Row="2" Grid.Column="1" Text="{x:Bind Model.TextBoxValue, Mode=TwoWay}"/>
    <TextBlock Grid.Row="3" Grid.Column="1" Text="{x:Bind Model.TextBoxValue, Mode=OneWay}"/>
    <Button Grid.Row="4" Content="Submit" Click="{x:Bind Model.ClickHandler}"/>
</Grid>

The CheckBox and TextBox are new, but probably pretty well known and self explanatory. The CheckBox has an IsChecked property, which is a nullable boolean value. Null represents the third state of a checkbox, usually used when a mix of child nodes are true and false. We set the initial value to false, or unchecked. The TextBox has a Text property, which is a string value. Notice the Mode=TwoWay in the bindings. Remember that the mode defaults to OneTime, and so in order to make the data flow back to the model we need to set this to TwoWay.

We also have a couple of TextBlock controls which will show what the current values of the model are. Like in the last example, we have a declaration and instantiation of the MainViewModel object in the MainPage.xaml.cs code behind file:

public sealed partial class MainPage : Page
{

    public MainPage()
    {
        this.InitializeComponent();
    }

    MainViewModel Model = new MainViewModel();

}

And then in the MainViewModel.cs file:

class MainViewModel : INotifyPropertyChanged
{
    bool? checkBoxValue = false;
    string textBoxValue;

    public bool? CheckBoxValue
    {
        get
        {
            return checkBoxValue;
        }

        set
        {
            checkBoxValue = value;
            NotifyPropertyChanged();
        }
    }

    public string TextBoxValue
    {
        get
        {
            return textBoxValue;
        }

        set
        {
            textBoxValue = value;
            NotifyPropertyChanged();
        }
    }

    public MainViewModel()
    {
    }


    public async void ClickHandler(object sender, RoutedEventArgs e)
    {
        var dlg = new Windows.UI.Popups.MessageDialog(string.Format("CheckBox:{0}, TextBox:{1}", CheckBoxValue, TextBoxValue));
        await dlg.ShowAsync();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    } 

}

The ClickHandler method has been updated to show a MessageDialog with the current values. Since the MessageDialog.ShowAsync method is anynchronous, we await the result of this method call. Since we await the result, we need to make the calling method async, which is fine, the Click event  still wires up properly.

If you run this sample, you’ll see something like this:

image

If you click the CheckBox, then you will see the TextBlock representing the CheckBox result change:

image

Now if you enter text into the TextBox, you might think that you should see the changes as you type, but for a TextBox the value doesn’t update until the TextBox loses focus, so you can click anywhere else or on the Submit button, and then you will see the TextBox result field show the current value:

image

and then if you click the submit button, you should see the current values in the model:

image

If you needed the current value of the text in the TextBox as you type, you could wire up the TextChanged event and check what the current value of the Text property is. The assumption is that you normally won’t need that value until you are done typing and click away.

Until next time…

XAML 101: More Data Binding

Sample code for this post on GitHub: https://github.com/billreiss/xamlnative/tree/master/Xaml101/016_MoreDataBinding

In the last post there was a brief introduction to data binding in Windows 10 apps. Let’s build upon this a bit. Previously we defined a string field and a string property in the MainPage.xaml.cs code behind file then used the x:Bind markup extension in the XAML to bind to these values.  This works fine in this case, but it is generally considered a best practice to separate your views from your data. Let’s add a new class to the last sample and call it MainViewModel.cs. Here is the body of that class:

class MainViewModel
{
    public string FieldBindingText = "Here is a Field Binding";

    public MainViewModel()
    {
        this.PropertyBindingText = "This is a Property Binding";
    }

    public string PropertyBindingText
    {
        get;
        set;
    }
}

Then in the MainPage.xaml.cs file, we can create an instance of this model class:

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
    }

    MainViewModel Model = new MainViewModel();
}

And then finally in the MainPage.xaml we can bind the values like this:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel>
        <TextBlock Text="{x:Bind Model.FieldBindingText}"/>
        <TextBlock Text="{x:Bind Model.PropertyBindingText}"/>
    </StackPanel>
</Grid>

Notice the small difference from the last sample, where now we are binding to Model.FieldBindingText instead of just FieldBindingText. This is because we have a field named Model in the MainPage.xaml.cs code behind and then we can reference sub-elements using dot notation.

Running this gives us the same result as before:

image

Now after the TextBlock in the XAML, let’s add a Button we can click:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel>
        <TextBlock Text="{x:Bind Model.FieldBindingText}"/>
        <TextBlock Text="{x:Bind Model.PropertyBindingText}"/>
        <Button Content="Click Me!" Click="Button_Click"/>
    </StackPanel>
</Grid>

Notice the Button has a Content property and not a Text property like a TextBlock has. This is because the button content can be just about anything. More about that in future posts. There is a click event specified here, so we need to implement this in the MainPage.xaml.cs file:

private void Button_Click(object sender, RoutedEventArgs e)
{
    Model.PropertyBindingText = "Clicked!";
}

Notice that the button’s click even changes the value of Model.PropertyBindingText. If we run the app, we get this:

image

And if we click the button, what will happen? You might expect the text of the second TextBlock to change. Actually what happens is nothing. There are a couple of reasons for this. The first is that there are a few data binding modes available, and the default is OneTime. One time binding means that the value is evaluated when the page is loaded and never again. This is the default because it is the most efficient and fast, and so unless you need a different mode for some reason XAML tries to help you write fast apps.

Other options are OneWay and TwoWay. A one way binding only goes from the source to the target, and  any changes to the target aren’t reflected in the source. With a two way binding, data flows in both directions.

NOTE: In other XAML platforms like WPF, the default is OneWay or in some cases TwoWay depending on the control.

Let’s change the TextBlock binding to a OneWay binding.

<TextBlock Text="{x:Bind Model.PropertyBindingText, Mode=OneWay}"/>

This however is still not enough. It’s not enough for the source value to change. We also need to notify XAML that the value has changed. This is done through the INotifyPropertyChanged interface. The INotifyPropertyChanged interface has a single event defined in it, an event we need to fire when the property changes. Here is a refactored MainViewModel.cs that implements INotifyPropertyChanged:

class MainViewModel : INotifyPropertyChanged
{
    public string FieldBindingText = "Here is a Field Binding";

    public MainViewModel()
    {
        this.PropertyBindingText = "This is a Property Binding";
    }

    string propertyBindingText;
    public string PropertyBindingText
    {
        get
        {
            return propertyBindingText;
        }
        set
        {
            propertyBindingText = value;
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("PropertyBindingText"));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

Now if you run it again and click the button you should see this:

image

It is so common to have to raise the property changed event that most helper frameworks like the great MVVM Light framework created by Laurent Bugnion provide a base class for this with a simple method call to raise the property changed event. In our MainViewModel class we can add the following method:

private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
} 

Notice the [CallerMemberName] attribute. This takes the name of the caller as the property name if it’s not specified. This keeps us from having to use hard coded strings when calling the notify property changed method. Hard coded strings can lead to problems when renaming and refactoring, and can also be easily mistyped. Then to use this method, the PropertyBindingText property can be changed to look like this:

public string PropertyBindingText
{
    get
    {
        return propertyBindingText;
    }
    set
    {
        propertyBindingText = value;
        NotifyPropertyChanged();
    }
}

And if you run the app again you should see the same result as before.

So we’re doing a good job of separating the view from the data and linking them together with data binding, but there is one thing that isn’t in the model and that’s the click event handler. It’s generally not considered good design to call into the model directly from the view, but in some cases it makes sense to do it. Here we can easily fix this with xBind by moving the click handler to the model as well.

Remove the event handler from MainPage.xaml.cs and then add this to MainViewModel.cs:

public void ClickHandler(object sender, RoutedEventArgs e)
{
    PropertyBindingText = "Clicked!";
}

And the XAML changes to this:

<Button Content="Click Me!" Click="{x:Bind Model.ClickHandler}"/>

Running this gives us the same result, but the view has nothing special in it except a declaration and instantiation of the MainViewModel class, and all of our data and logic is in one place. If you don’t need the sender and the args in the method that handles the event, you can make it a method without arguments like this and it will work fine:

public void ClickHandler()
{
    PropertyBindingText = "Clicked!";
}

Note that you may need to rebuild all on the solution for it to regenerate the bindings. Next time we’ll dig even deeper into data binding.

XAML 101: Getting Started with Data Binding

Source code for this post on GitHub: https://github.com/billreiss/xamlnative/tree/master/Xaml101/015_DataBinding

Data binding is a huge topic in XAML, it’s pervasive and whether you are following the Model View ViewModel (MVVM) design pattern that’s very popular in XAML or  if you just want to populate a list of elements, you’ll probably need to use data binding in some form in your app. We will cover some now, and then there will probably be more topics as we progress.

Data binding has been around a long time. You could do it in Windows Forms apps. PowerShell and Delphi were built around it. I feel that with XAML they finally got it right, and it has made it to the point where if you’re not using it to build your app, you may be doing it wrong.

Data binding gives you a bridge between the data and the layout, and reduces the code you need to write to wire these two parts together. In earlier XAML based frameworks (WPF, Silverlight, WinRT for Windows 8) data binding was very dynamic and a lot was done at run time using reflection to make it work. Reflection is slow and memory intensive. When the Windows Shell team and the Office team started using XAML to develop Windows 10 apps and shell components, they ran into these performance and resource issues and came back to the Windows 10 Universal Windows Platform (UWP) team and asked for guidance. These teams are so focused on performance and will reject a technology if it doesn’t fit their needs. At first the UWP team considered guiding them to not use data binding and just wire up everything in code, which is what was typical in WinForms apps. Then they came up with a better way. More about it here. There is a new data binding system in Windows 10 UWP and it removes most of the old concerns about performance issues in traditional data binding in XAML. We won’t cover the old method of data binding, at least not yet, because I feel it’s best to lead in the recommended direction for best practices.

So what’s different about the new way? The heavy lifting is done at compile time. Code is generated to improve performance. No reflection is used. Binding errors are found at compile time. You can put breakpoints in the generated code. The defaults are set to maximize performance. Unless it doesn’t do what you need in some specific situation, I recommend using the new way. The new way is referred to as compiled bindings, or xBind.

Data bindings in general or xBind in particular are XAML markup extensions. We have seen some of these already, specifically ThemeResource and StaticResource. It’s a bit of a testament to XAML that Microsoft was able to swap out the data binding strategy.

NOTE: Compiled bindings are only currently available in Windows 10 UWP apps. I would love to see them in WPF too, if you agree go vote for it at http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/7810488-implement-x-bind-for-wpf. Microsoft really pays attention to this and you can make a difference.

In over 15 posts so far in the  XAML 101 series, I don’t think we have actually left XAML and written a line of C# code. There is only so much you can do in straight XAML and at some point the data needs to come from somewhere. Later we’ll dig into some design patterns and some suggestions on how to organize your code but data binding is useful without all of that.

Let’s look at a couple of very simple data binding examples, and then we can go from there in future posts. Consider these changes to the MainPage.xaml.cs file:

public sealed partial class MainPage : Page
{
    string FieldBindingText = "Here is a Field Binding";
    string PropertyBindingText
    {
        get; set;
    }

    public MainPage()
    {
        this.InitializeComponent();
        this.PropertyBindingText = "This is a Property Binding";
    }
}

We have two strings, one is a field and one is a property. Now in the MainPage.xaml we can do this:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel>
        <TextBlock Text="{x:Bind FieldBindingText}"/>
        <TextBlock Text="{x:Bind PropertyBindingText}"/>
    </StackPanel>
</Grid>

Notice the Text properties use the x:Bind markup extension, and the names match the string field and property we created in the code behind file. The compile bindings markup extension automatically looks to the current class definition for matching elements. running the app looks like this:

image

Let’s then change the first TextBlock to look like this:

<TextBlock Text="{x:Bind aFieldBindingText}"/>

Since the name specified no longer can find a match, we get a compile time error:

image

That’s it for now, stay tuned.

XAML 101: Resource Dictionaries

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

We have seen how to create our own resources, use built in resources and styles, and create styles of our own. This gives us a lot of power over the layout of our app, but all of these resource definitions can clutter our pages and/or the App.xaml file. You also might want to reuse your resource definitions on other pages or in other apps, and that his hard to do if you have these resources defined inline unless you just copy/paste everything. Fortunately there is a better way by using resource dictionaries.

A Resource Dictionary is a special type of XAML file that contains a set of resource definitions. Let’s add one to our project. First let’s create a new folder in the project called Resources. This isn’t required but I feel it’s good to organize a bit. Select this new folder then in the Project menu select Add New Item (you can also right click on the Resources folder and select it there):

image

Now you should see the types of new items you can create. One of them will be Resource Dictionary. We’ll call it MyResources.xaml.

image

This is what Visual Studio creates for us:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HelloXaml.Resources">
    
</ResourceDictionary>

Consider this XAML where we declare a Style in the Page Resources:

<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">
    <Page.Resources>
        <Style x:Key="TitleBlueStyle" BasedOn="{StaticResource TitleTextBlockStyle}" TargetType="TextBlock">
            <Setter Property="Foreground" Value="Blue"/>
        </Style>
    </Page.Resources>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel>
            <TextBlock Text="Here is some text" Style="{StaticResource TitleBlueStyle}"/>
            <TextBlock Text="Some more text"/>
            <TextBlock Text="3rd line of text"/>
        </StackPanel>
    </Grid>
</Page>

And this what the the app looks like when running:

image

We can move the Style definition to the MyResources.xaml file:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HelloXaml.Resources">
    <Style x:Key="TitleBlueStyle" BasedOn="{StaticResource TitleTextBlockStyle}" TargetType="TextBlock">
        <Setter Property="Foreground" Value="Blue"/>
    </Style>
</ResourceDictionary>

And then we can use this resource dictionary in our page:

<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">
    <Page.Resources>
        <ResourceDictionary Source="Resources/MyResources.xaml"/>
    </Page.Resources>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel>
            <TextBlock Text="Here is some text" Style="{StaticResource TitleBlueStyle}"/>
            <TextBlock Text="Some more text"/>
            <TextBlock Text="3rd line of text"/>
        </StackPanel>
    </Grid>
</Page>

And this will give us the same result. So this is great if we have one file with all our resource definitions in it, and then we can just reference it like this in each page, or we could reference it in the App.xaml file so the whole app can have access to these resources:

<Application
    x:Class="HelloXaml.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HelloXaml"
    RequestedTheme="Light">
    <Application.Resources>
        <ResourceDictionary Source="Resources/MyResources.xaml"/>
    </Application.Resources>
</Application>

But what if we have more than one resource dictionary to combine? This could happen if you have a fairly large app, and you want to keep your resources manageable. This can be done using the MergedDictionaries property like this:

<Application
    x:Class="HelloXaml.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HelloXaml"
    RequestedTheme="Light">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Resources/MyResources.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

The MergedDictionaries property can take a list of ResourceDictionary entries so that you can break down your resources in any way that makes sense to your development process.

XAML 101: Built in Styles and “Cascading”

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

In the last post, we looked at how you can create your own styles and use those to provide a consistent look and feel to your application. There are also some styles that are provided for you that can give your app a consistent look with other Universal Windows Platform apps. Consider the following XAML:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel>
        <TextBlock Text="Here is some text"/>
        <TextBlock Text="Some more text"/>
        <TextBlock Text="3rd line of text"/>
    </StackPanel>
</Grid>

Select the first TextBlock, and in the Properties pane go to the Style property and click the “peg” next to it, and under System Resources select “TitleTextBlockStyle”. Your XAML should now look like this:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel>
        <TextBlock Text="Here is some text" Style="{StaticResource TitleTextBlockStyle}"/>
        <TextBlock Text="Some more text"/>
        <TextBlock Text="3rd line of text"/>
    </StackPanel>
</Grid>

And the app looks like this:

image

Notice that this is a StaticResource and not a ThemeResource. This is because it is not defined in the themed resources section of the built in resources files. We can take a look at the definition for this style by right clicking in the XAML on the TitleTextBlockStyle and then choose Go To Definition.

image

And here is the definition you will see:

<Style x:Key="TitleTextBlockStyle" TargetType="TextBlock" BasedOn="{StaticResource BaseTextBlockStyle}">
    <Setter Property="FontWeight" Value="SemiLight"/>
    <Setter Property="FontSize" Value="24"/>
    <Setter Property="OpticalMarginAlignment" Value="TrimSideBearings"/>
</Style>

It looks a lot like the one we created in the last post. There is however one extra thing here. See the BasedOn property on the Style object? This is how XAML does something similar to “cascading” in HTML and CSS, where one style is based on another. This allows you to create a base style, then create a new style based on that one, and adjusting the values of the properties you need. This is the definition of the BaseTextBlockStyle:

<Style x:Key="BaseTextBlockStyle" TargetType="TextBlock">
    <Setter Property="FontFamily" Value="Segoe UI"/>
    <Setter Property="FontWeight" Value="SemiBold"/>
    <Setter Property="FontSize" Value="15"/>
    <Setter Property="TextTrimming" Value="None"/>
    <Setter Property="TextWrapping" Value="Wrap"/>
    <Setter Property="LineStackingStrategy" Value="MaxHeight"/>
    <Setter Property="TextLineBounds" Value="Full"/>
</Style>

So the FontWeight and FontSize properties are overridden in the child style, but everything else will be inherited.

We can do the same thing, and base a Style on the built in TitleTextBlockStyle.

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.Resources>
        <Style x:Key="TitleBlueStyle" TargetType="TextBlock" BasedOn="{StaticResource TitleTextBlockStyle}">
            <Setter Property="Foreground" Value="Blue"/>
        </Style>
    </Grid.Resources>
    <StackPanel>
        <TextBlock Text="Here is some text" Style="{StaticResource TitleBlueStyle}"/>
        <TextBlock Text="Some more text"/>
        <TextBlock Text="3rd line of text"/>
    </StackPanel>
</Grid>

Here we inherit from TitleTextBlockStyle and set the Foreground to Blue, and then use this new style on the TextBlock. This is how the app looks now:

image

XAML 101: Getting Started with Styles

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

So far we have seen ThemeResources and also created our own Resources that we can then use with the StaticResource markup extension. We can mix and match these to customize any element in our XAML.

Consider the XAML from the last post:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.Resources>
        <SolidColorBrush x:Key="redBrush" Color="Red"/>
    </Grid.Resources>
    <StackPanel>
        <TextBlock Text="Here is some text" Foreground="{StaticResource redBrush}"/>
        <TextBlock Text="Some more text" Foreground="{StaticResource redBrush}"/>
        <TextBlock Text="3rd line of text" Foreground="{StaticResource redBrush}"/>
    </StackPanel>
</Grid>

Let’s add the use of a built in themed resource to set the font size. Select the first TextBlock, and then in the Properties pane (I like to Arrange by Name, I think it’s easier to find things that way) look for the FontSize property. It should be showing a value of 15, the default font size for a TextBlock. Click the little “peg” next to it.

image

This brings up a menu with a few options. Pick System Resource then TextStyleExtraLargeFontSize. The XAML should now look like this:

<TextBlock Text="Here is some text" Foreground="{StaticResource redBrush}" FontSize="{ThemeResource TextStyleExtraLargeFontSize}"/>

You can copy and paste this FontSize property to the other TextBlocks, or set each the same way we set the first one.

Now we have some large red text.

image

Now it’s right up against the edge, so let’s add a Margin to each TextBlock:

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.Resources>
            <SolidColorBrush x:Key="redBrush" Color="Red"/>
        </Grid.Resources>
        <StackPanel>
            <TextBlock Text="Here is some text" 
                       Margin="10,0,10,0" 
                       Foreground="{StaticResource redBrush}" 
                       FontSize="{ThemeResource TextStyleExtraLargeFontSize}"/>
            <TextBlock Text="Some more text" 
                       Margin="10,0,10,0" 
                       Foreground="{StaticResource redBrush}" 
                       FontSize="{ThemeResource TextStyleExtraLargeFontSize}"/>
            <TextBlock Text="3rd line of text" 
                       Margin="10,0,10,0" 
                       Foreground="{StaticResource redBrush}" 
                       FontSize="{ThemeResource TextStyleExtraLargeFontSize}"/>
        </StackPanel>
    </Grid>

Now it looks like this:

image

This is fine, and we are getting the results we want, but now we’re back to the fragility problem where we have to change things in multiple places if we want to change the design of the app. This is where Styles come in. You may be familiar with styles in HTML using CSS, and generally you can think about these the same way.

Styles in XAML allow you to specify values for multiple properties and apply them to a control. There are some other things you can do with styles too, and we will see those over time, but let’s get through the basics now.

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.Resources>
        <SolidColorBrush x:Key="redBrush" Color="Red"/>
        <Style x:Key="redLargeTextStyle" TargetType="TextBlock">
            <Setter Property="Margin" Value="10,0,10,0"/>
            <Setter Property="Foreground" Value="{StaticResource redBrush}"/>
            <Setter Property="FontSize" Value="{ThemeResource TextStyleExtraLargeFontSize}"/>
        </Style>
    </Grid.Resources>
    <StackPanel>
        <TextBlock Text="Here is some text" Style="{StaticResource redLargeTextStyle}"/>
        <TextBlock Text="Some more text" Style="{StaticResource redLargeTextStyle}"/>
        <TextBlock Text="3rd line of text" Style="{StaticResource redLargeTextStyle}"/>
    </StackPanel>
</Grid>

This XAML defines a Resource of type Style, and gives it a key name so we can reference it where we want, and tells it what type of control this style applies to. The Style then contains a list of Setters with property names and values. We then set the Style property on each TextBlock to use the Style we defined as a Resource.

image

Things look just like they did before, but now if we want to change any of the property setter values, or add or remove style setters, we can do that all in one place and everywhere we use that style will be changed.

For example, if we want the text to be italic, we can add another setter to the Style:

<Style x:Key="redLargeTextStyle" TargetType="TextBlock">
    <Setter Property="Margin" Value="10,0,10,0"/>
    <Setter Property="Foreground" Value="{StaticResource redBrush}"/>
    <Setter Property="FontSize" Value="{ThemeResource TextStyleExtraLargeFontSize}"/>
    <Setter Property="FontStyle" Value="Italic"/>
</Style>

And then it looks like this:

image

You can override any property defined in the style by explicitly setting it on the control, like if we want the last line to be blue:

<TextBlock Foreground="Blue" Text="3rd line of text" Style="{StaticResource redLargeTextStyle}"/>

image

Now let’s say you wanted to have your style applied to all TextBlocks without setting the Style property on each of them. For this we can define an implicit style. This is easy enough to do, just don’t specify an x:Key value on your Style. Then this will be the default style for that type of control. Note that you can still override this by specifying a value for the Style property.

XAML 101: Creating your own Resources

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

A couple of posts ago, we looked at Themes and how you can use them to specify colors and other properties that would change with the currently selected theme. This was done through resource dictionaries, resource definitions and the ThemeResource markup extension.

The ThemeResources are used for consistency, but you may have consistency you want to enforce in your app to enforce the unique style of your app. Consider the following:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel>
        <TextBlock Text="Here is some text" Foreground="Red"/>
        <TextBlock Text="Some more text" Foreground="Red"/>
        <TextBlock Text="3rd line of text" Foreground="Red"/>
    </StackPanel>
</Grid>

And this is how it looks:

image

All the TextBlocks have a Foreground of Red, and this is fine and consistent, but if we wanted to change the foreground color, this is pretty fragile because we would need to change it in 3 places, and as the app grows, we would need to change it more.

A better way is to define a resource:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.Resources>
        <SolidColorBrush x:Key="redBrush" Color="Red"/>
    </Grid.Resources>
    <StackPanel>
        <TextBlock Text="Here is some text" Foreground="{StaticResource redBrush}"/>
        <TextBlock Text="Some more text" Foreground="{StaticResource redBrush}"/>
        <TextBlock Text="3rd line of text" Foreground="{StaticResource redBrush}"/>
    </StackPanel>
</Grid>

The StaticResource markup extension will look for any resources with a matching x:Key in any parent element, or in an application-wide resource definition. If we want the resource definition to apply to the whole page,  then the resource definition can be at the page level:

<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">
    <Page.Resources>
        <SolidColorBrush x:Key="redBrush" Color="Red"/>
    </Page.Resources>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel>
            <TextBlock Text="Here is some text" Foreground="{StaticResource redBrush}"/>
            <TextBlock Text="Some more text" Foreground="{StaticResource redBrush}"/>
            <TextBlock Text="3rd line of text" Foreground="{StaticResource redBrush}"/>
        </StackPanel>
    </Grid>
</Page>

The most common case is probably that you would want this resource definition to be available anywhere in your app. To do this you can make the definition in your App.xaml file:

<Application
    x:Class="HelloXaml.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HelloXaml"
    RequestedTheme="Light">
    <Application.Resources>
        <SolidColorBrush x:Key="redBrush" Color="Red"/>
    </Application.Resources>
</Application>

XAML 101: The StackPanel

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

So far when looking at elements that contain other elements we have seen the Border and the Grid. Another useful container is the StackPanel. If you are familiar with Android development, the closest relation is to the LinearLayout control. The StackPanel lets you arrange elements in sequence one after the other either vertically or horizontally.

NOTE: When I was working closely with designers in Silverlight (a XAML based framework) they would usually take my StackPanels and convert them to Grids with Rows or Columns, they liked the level of control they had over the layout better. There are some drawbacks to StackPanel especially when it comes to horizontal StackPanels and fitting the available space. It’s usually not as much of a problem vertically and it is more common to use StackPanel in vertical mode. The StackPanel is an important component of ListView and other list based controls we will see later.

In the last post we had some text in the grid, but what if we wanted a few lines of text. One way to do this is to use a StackPanel:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel>
        <TextBlock Text="Here is some text"/>
        <TextBlock Text="Some more text"/>
        <TextBlock Text="3rd line of text"/>
    </StackPanel>
</Grid>

And this is how it looks:

image

The Orientation property on the StackPanel defaults to Vertical but we can change it to Horizontal:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Here is some text"/>
        <TextBlock Text="Some more text"/>
        <TextBlock Text="3rd line of text"/>
    </StackPanel>
</Grid>

And here is how it looks:

image

I haven’t seen many cases where a Horizontal StackPanel is the best option. Usually there is a better solution, it could be a Grid with Columns, or a RelativePanel, we will see the RelativePanel soon.

XAML 101: Themes

Up until this point, we have been ignoring a piece of the XAML that is generated by default when a new Universal app is created. Consider this line:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

What’s with those curly braces and the content inside them in the Background property? First of all, the braces denote a XAML Markup Extension. There are several types of these, and we will see more in the future. This one is a ThemeResource markup extension. Markup extensions provide extra functionality when you need to do something other than specifying a value. The ThemeResource extension gives you consistency in your user interface by being able to specify predefined values for properties.

If you right click on ApplicationPageBackgroundThemeBrush and go to definition, you can see where it is defined.

image

This brings up a file called generic.xaml with this definition in it:

<SolidColorBrush x:Key="ApplicationPageBackgroundThemeBrush" Color="#FFFFFFFF" />

The x:Key property lets us reference this resource by name. This definition is inside a ResourceDictionary with an x:Key of “Light”:

<ResourceDictionary x:Key="Light">

This ResourceDictionary is inside a ThemeDictionaries property. There are two other ResourceDictionary entries here too, namely “Default”, and “HighContrast”. Default is used when the theme is set to the dark theme, and HighContrast is for when the device is in high contrast mode. The ThemeResource markup extension picks the right resource definition to use based on the key and the current theme.

NOTE: Themes were always a big reason for failures when submitting an app on Windows Phone 8.1 and earlier. Developers wouldn’t test their app in light theme (the default on Windows Phone was dark theme) and they would have text or other elements that wouldn’t be visible in light theme. Unless you forced it otherwise, on Windows Phone the theme for your app would follow what the user had selected for the system. Jeff Wilcox had a great tool for forcing the theme to a specific value http://www.jeff.wilcox.name/2012/01/phonethememanager/

In Windows 10, the developer has more control over the theme.

There are two different places where a theme is important. Once is at design time when we want to see how an app looks with a specific theme, and then when the app is run, so we can say what theme we prefer for our app. First let’s look at design time. If we have a MainPage.xaml file that has a Grid like this:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <TextBlock Text="Here is some text"/>
</Grid>

In the XAML designer in Visual Studio we see this:

image

See that gear at the top? If we click on that we get this:

image

If you change Theme to Dark you can see what your page will look like if the theme is set to dark:

image

Now this setting is only for design time. At run time, the app will default to light theme unless you specify otherwise. This is done in the App.xaml file, here is what is generated by default:

<Application
    x:Class="HelloXaml.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HelloXaml"
    RequestedTheme="Light">

</Application>

If you change RequestedTheme to “Dark”, then your app will use the dark theme. I think it’s a good idea to make sure your design time settings and the setting in App.xaml match so that you can see what it’s really going to look like.