XAML

Beware of using Edit Template in a UWP app

Hello Devs,

When Microsoft released the Windows 10 April 2018 update, I installed it and I updated Visual Studio with the latest SDK. If you develop UWP apps where the min version is set to the latest Windows update (in this case Windows 10, version 1803, build 17134), you can stop reading here. However, if for example, the min version if the Fall Creators Update, please read on.

image

The other day, I was testing on my desktop machine the style that I modified of a simple TextBox. It was working well, until I deployed on my Dell Venue Pro 8. When I navigated to a page where I modified the TextBox, the app crashes every single time. I was wondering what was going on since Visual Studio didn’t warn me of anything.

If you add an TextBox and you click on “Edit Template”, the latest SDK will introduce the usage of the ThemeResource IsApplicationFocusVisualKindReveal. This resource does not exist in previous Windows 10 updates, so when the app runs on previous version, the app will crash.

image

What is worrisome is Visual Studio does not warn about anything (no warning message and no wiggle underline under the resource name).

I wrote an email to my XAML friends at Microsoft and they acknowledged what I found. They were actually surprised by that too. I will report back when they will find the solution for it.

In the meantime, I highly suggest that if you do an Edit Template with the April 10 SDK, go ahead and try in all of your supported Windows 10 updates.

Happy testing Smile

PS: it’s been quite a long time from my previous blog. Having kids and a new passion (Magic the Gathering competition) took a lot of my free time. I still work full time on UWP projects for years and I enjoy this more than ever!

NavigationCacheMode: A property that can save you a headache!

Windows 10 is here. There is no better time to start developing apps for the Windows 10 ecosystem.

If you are new to Windows 10 app development (or even 8.1 if you want to target Windows 8.1 / Windows Phone 8.1 users), there are some basic concepts that you need to learn: reactive design, application lifecycle, navigation, and so on.

This article is about one important property related to navigation (please continue to read!). If you develop an application that only has one page, you don’t have to worry about navigation. However, if your application has more than one page, you will need to use some navigation methods.

To illustrate the default behaviour of basic navigation, let’s create a Super Calculator application. You can download the sample here

1- Open any version of Visual Studio 2015 and go to “File \ New \ Project…” and select the template “Visual C# \ Windows \ Universal \ Blank App (Universal Windows)”. You can name the project “Super Calculator” and click OK.

image

2- Open the MainPage.xaml file and replace the Grid with:

<StackPanel
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    VerticalAlignment="Center">
        
    <TextBox
        x:Name="TextBoxNumber1"
        Width="200" />

    <TextBlock 
        Margin="0,10"
        Text="+"
        TextAlignment="Center"/>
        
    <TextBox
        x:Name="TextBoxNumber2"
        Width="200" />
        
    <Button Click="OnButtonCalculate"
            Content="Calculate"
            HorizontalAlignment="Center"
            Margin="0,10,0,0"/>

</StackPanel>

3- Open the MainPage.xaml.cs file and add the following method:

private void OnButtonCalculate(object sender, RoutedEventArgs e)
{
    int number1 = int.Parse(TextBoxNumber1.Text);
    int number2 = int.Parse(TextBoxNumber2.Text);

    this.Frame.Navigate(typeof(ResultPage), number1 + number2);
}

Here Frame.Navigate will navigate to the page specified with the type of the class.

4- Right-Click on the project SuperCalculator and select “Add \ New item… \ Blank Page”. Rename BlankPage1.xaml to ResultPage.xaml and click OK.

image

5- Open the ResultPage.xaml file and add the following inside the Grid:

<StackPanel 
    HorizontalAlignment="Center"
    VerticalAlignment="Center">

    <TextBlock
        Text="Result" />
            
    <TextBlock
        x:Name="TextBlockResult"
        FontSize="25"/>
            
    <Button 
        Click="OnButtonBack"
        Content="Back"
        Margin="0,10,0,0"/>

</StackPanel>

6- Open the ResultPage.xaml.cs file and add these two methods:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    TextBlockResult.Text = e.Parameter.ToString();
}

private void OnButtonBack(object sender, RoutedEventArgs e)
{
    Frame.GoBack();
}

Here Frame.GoBack will return to the previous page in the stack. In our case, it returns to the MainPage.

7- Run the application and put numbers in the 2 fields and click on the button Calculate.

You will see the expected result. However, what do you think will happen if you click on the Back button? There are 2 possibilities:

a) Navigation to the MainPage will include the numbers that you entered.
b) Navigation to the MainPage will reset the numbers that you entered.

If you are familiar with the Silverlight model, you know that returning to the MainPage will include the numbers. However, in Windows 10, the MainPage will be instantiated again and the numbers will be reset. The decision is debatable, but we have to deal with it and fortunately, Microsoft offers the property NavigationCacheMode if you want to override the default behaviour of instantiating the page again.

For the pages that you want to preserve in memory, you only have to add NavigationCacheMode=”Required” to the page declaration.

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

Note: don’t try to change the NavigationCacheMode outside the page declaration in XAML or in the constructor, it will not work.

The NavigationCacheMode offers the “Enabled” value that will preserve the page in memory if the cache limit of the frame is not exceeded. Personally, I prefer to set the value to “Disabled” or “Required” value.

There are lots of scenarios where you will set the NavigationCacheMode to Required. One example is when a page contains a GridView or a ListView with many items. If a user clicks on an item to consult the details on another page, don’t make him scroll again when he returns. Not only will the user’s experience be better, the page will return faster because there is nothing to load as everything is in memory.

If you want to know more about Windows 10, here is a list of great resources from Microsoft (all free):

Happy coding!

XAML coding convention

Over the past year, I have built my own coding conventions for C#. I also always manage to convince my colleagues to follow my coding convention if they don’t already have one. I’m a real freak about following coding conventions; if I see someone modifying one of my files and not following my conventions, I might have trouble sleeping at night (ok, not that much, but…).

With the help of the great Visual Studio add-on ReSharper, it’s easy to format code with rules. You only need to press Ctrl-E/Ctrl-C to format a document. ReSharper is a must have tool for Visual Studio.

For the past two years, since the release of the Windows Phone platform, I have been using the XAML language to program my user interfaces. Finding coding conventions for C# is pretty easy, but for XAML, it was a bit more of a challenge. My first move was to check the default Microsoft projects, but I concluded that even they are a bit messy even for today.

Here is an example of a WIndows Store Grid App project:

<ListView.GroupStyle>
    <GroupStyle>
        <GroupStyle.HeaderTemplate>
            <DataTemplate>
                <Grid Margin="7,7,0,0">
                    <Button
                        AutomationProperties.Name="Group Title"
                        Click="Header_Click"
                        Style="{StaticResource TextPrimaryButtonStyle}">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding Title}" Margin="3,-7,10,10" Style="{StaticResource GroupHeaderTextStyle}" />
                            <TextBlock Text="{StaticResource ChevronGlyph}" FontFamily="Segoe UI Symbol" Margin="0,-7,0,10" Style="{StaticResource GroupHeaderTextStyle}"/>
                        </StackPanel>
                    </Button>
                </Grid>
            </DataTemplate>
        </GroupStyle.HeaderTemplate>
    </GroupStyle>
</ListView.GroupStyle>

First of all, there are not any empty lines, and secondly the button has attributes on separate lines, but for the TextBlock elements, the attributes are on the same lines without any order.

With time, I developed my own XAML coding convention that I would like to share. One of the reasons that I developed my own XAML coding convention is I don’t like to use the Properties window, because it is hard to have an overview of the properties that are not set to default.

image

My coding convention is resumed in 5 points:

1- Put empty lines between elements.

Don’t be afraid to put empty lines. It makes reading the code easier.

<Grid Height="250"
      VerticalAlignment="Top">

    <Image Source="{Binding FeatureArticle1.Thumbnail}"
           Style="{StaticResource ImageThumbnailStyle}" />

    <StackPanel Style="{StaticResource StackPanelSummaryStyle}">

    <TextBlock FontSize="22"
               Style="{StaticResource TextBlockAuthorStyle}"
               Text="{Binding FeatureArticle1.Author}" />

    <TextBlock FontSize="26"
               Height="70"
               Style="{StaticResource TextBlockSummaryStyle}"
               Text="{Binding FeatureArticle1.Title}" />

    </StackPanel>

</Grid>

My exceptions are the Grid.ColumnDefinition and Grid.RowDefinitions, because they only have one line attribute.

<Grid.ColumnDefinitions>
    <ColumnDefinition Width="200" />
    <ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>

<Grid.RowDefinitions>
    <RowDefinition Height="200" />
    <RowDefinition Height="140" />
</Grid.RowDefinitions>

2- Put one attribute per line.

<TextBlock FontWeight="Bold"
           Foreground="White"
           HorizontalAlignment="Right"
           Margin="0,0,12,0"
           Text="{Binding ArticlesCountText}"
           TextWrapping="Wrap" />

3- Order the attributes alphabetically.

<Image Source="/Assets/Shares/NeutralImage.png"
       Height="125"
       HorizontalAlignment="Center"
       Width="125"
       Stretch="UniformToFill"
       VerticalAlignment="Center" />

Some will argue that Height and Width should be side by side or on the adjacent line, but I still prefer the alphabetical order, because it is much easier to read when you know what order your definitions are in. Also, if there is an element with many attributes, it is much easier to check whether an attribute is missing.

4- Put the attached properties at the beginning and in an alphabetic order.

<Button Grid.Column="1"
        Grid.Row="2"
        Command="{Binding ShowWriterCommand}"
        CommandParameter="{Binding WriterAshley}"
        Style="{StaticResource HubTileButtonStyle}" />

The Grid.Column / Grid.Row are the classic examples.

5- Definition of styles can be less strict.

When I’m creating styles with Expression Blend, I tend to leave them as-is when they are big. It is more about saving time than anything else. However, when a style is small, I don’t put empty lines and I put the properties in an alphabetic order like this:

<Style x:Key="GridFeatureStyle"
        TargetType="Grid">
    <Setter Property="Height"
            Value="194" />
    <Setter Property="VerticalAlignment"
            Value="Top" />
    <Setter Property="Width"
            Value="194" />
</Style>


Conclusion

It might not be the perfect solution for you, but if you do not have one, my convention is a good start especially if you are sharing code with colleagues.

My motto about coding convention is the following: it is better to have a coding convention than not having one!

Happy coding!