Highlight of useful Windows Desktop UI components

This post has been republished via RSS; it originally appeared at: New blog articles in Microsoft Tech Community.

Windows UI features are being improved really high speed. Those features are very helpful to create beautiful Windows apps.

 

In this article, I explain some features I picked up. Let's start to create beautiful Windows app with new Windows UI features!

 

ItemsRepeater control

ItemsRepeater is very powerful and simple UI control. It is part of the Windows UI Library.

We can use it through the Microsoft.UI.Xaml NuGet package. 

 

Let's add the package to an UWP project. And then add following XAML snippets to App.xaml.

<Application.Resources>
    <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
</Application.Resources>

ItemsRepeater can use same as other List controls like ListView, ItemsControl, GridView, etc...

If you want to show items, it can be just bind a collection to ItemsSource property like this:

<Page
    x:Class="WinUILab.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WinUILab"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:controls="using:Microsoft.UI.Xaml.Controls"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <controls:ItemsRepeater ItemsSource="{x:Bind Items}" />
    </Grid>
</Page>

The Items property is defined at code behind like below:

public sealed partial class MainPage : Page
{
    public ObservableCollection<string> Items { get; } = new ObservableCollection<string>
    {
        "First item", "Second item", "Third item", "Fourth item", "Fifth item",
    };

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

The following image is result that is run the above code.

コメント 2019-05-24 124455.jpg

Of cause, it can customize how to display the data using DataTemplate.

<Page
    x:Class="WinUILab.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WinUILab"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:controls="using:Microsoft.UI.Xaml.Controls"
    xmlns:system="using:System"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <controls:ItemsRepeater ItemsSource="{x:Bind Items}">
            <controls:ItemsRepeater.ItemTemplate>
                <DataTemplate x:DataType="system:String">
                    <Grid Margin="5">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition />
                        </Grid.ColumnDefinitions>
                        <Rectangle Width="30" Height="30" Fill="{ThemeResource SystemControlBackgroundAccentBrush}"
                                   Margin="5,0" Grid.RowSpan="2" />
                        <TextBlock Text="{x:Bind}"
                                   Style="{StaticResource BodyTextBlockStyle}" 
                                   Grid.Column="1" />
                        <TextBlock Text="{x:Bind x:String.Format('Length: {0} chars', Length)}"
                                   Style="{StaticResource BodyTextBlockStyle}" 
                                   Grid.Row="1" Grid.Column="1" />
                    </Grid>
                </DataTemplate>
            </controls:ItemsRepeater.ItemTemplate>
        </controls:ItemsRepeater>
    </Grid>
</Page>

コメント 2019-05-24 125940.jpg

Good. However, we have no scroll features yes. For example, if I changed Items property like below:

// 10,000 items!?
public ObservableCollection<string> Items { get; } = new ObservableCollection<string>(
    Enumerable.Range(1, 10000).Select(x => $"Item: {x}"));

It can't scroll.

コメント 2019-05-24 130511.jpg

But no worries, we can get scroll bars(both of horizontal and vertical), just wrap ItemsRepeater to ScrollViewer control.

<Page
    x:Class="WinUILab.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WinUILab"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:controls="using:Microsoft.UI.Xaml.Controls"
    xmlns:system="using:System"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <ScrollViewer>
            <controls:ItemsRepeater ItemsSource="{x:Bind Items}">
                <controls:ItemsRepeater.ItemTemplate>
                    <DataTemplate x:DataType="system:String">
                        <!-- Snip -->
                    </DataTemplate>
                </controls:ItemsRepeater.ItemTemplate>
            </controls:ItemsRepeater>
        </ScrollViewer>
    </Grid>
</Page>

We got a scroll bar.

scroll.gif

If you want to support prior to Windows 10 1809, then it has to do an additional step. Please read the ItemsRepeater documentation.

 

If you want selection feature, it can implement yourself.

For example:

Add a class for holder a list value.

using System;
using System.ComponentModel;

namespace WinUILab
{
    public class MyItem : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public string Value { get; }

        private bool _isSelected;

        public MyItem(string value)
        {
            Value = value ?? throw new ArgumentNullException(nameof(value));
        }

        public bool IsSelected
        {
            get => _isSelected;
            set
            {
                if (_isSelected == value) { return; }
                _isSelected = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsSelected)));
            }
        }

        public void SwitchSelection()
        {
            IsSelected = !IsSelected;
        }
    }
}

Bind Tapped event of Grid control to SwitchSelection method and change BackgroundColor by value of IsSelected property. 

<Page
    x:Class="WinUILab.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WinUILab"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:controls="using:Microsoft.UI.Xaml.Controls"
    xmlns:system="using:System"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Page.Resources>
        <SolidColorBrush x:Key="WhiteBrush" Color="White" />
        <local:BooleanConverter x:Key="BackgroundColorConverter"
                                TrueValue="{StaticResource ListViewItemSelectedBackgroundThemeBrush}"
                                FalseValue="{StaticResource WhiteBrush}" />

    </Page.Resources>
    <Grid>
        <ScrollViewer>
            <controls:ItemsRepeater ItemsSource="{x:Bind Items}">
                <controls:ItemsRepeater.ItemTemplate>
                    <DataTemplate x:DataType="local:MyItem">
                        <Grid Padding="5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                              Background="{x:Bind IsSelected, Converter={StaticResource BackgroundColorConverter}, Mode=OneWay}"
                              Tapped="{x:Bind SwitchSelection}">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition />
                            </Grid.ColumnDefinitions>
                            <Rectangle Width="30" Height="30" Fill="{ThemeResource SystemControlBackgroundAccentBrush}"
                                   Margin="5,0" Grid.RowSpan="2" />
                            <TextBlock Text="{x:Bind Value}"
                                   Style="{StaticResource BodyTextBlockStyle}" 
                                   Grid.Column="1" />
                            <TextBlock Text="{x:Bind x:String.Format('Length: {0} chars', Value.Length)}"
                                   Style="{StaticResource BodyTextBlockStyle}" 
                                   Grid.Row="1" Grid.Column="1" />
                        </Grid>
                    </DataTemplate>
                </controls:ItemsRepeater.ItemTemplate>
            </controls:ItemsRepeater>
        </ScrollViewer>
    </Grid>
</Page>

The BooleanConverter alsss is following:

using System;
using Windows.UI.Xaml.Data;

namespace WinUILab
{
    public class BooleanConverter : IValueConverter
    {
        public object TrueValue { get; set; }
        public object FalseValue { get; set; }
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            return (bool)value ? TrueValue : FalseValue;
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language) => throw new NotSupportedException();
    }
}

select.gif

If you interested ItemsRepeater, then please read the documentation.

https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/items-repeater#display-grouped-items

 

TeachingTip control

TeachingTip also provides via Windows UI Library. It is a useful control to display a help message to use some control on your app.

This is easy to use. You just add TeachingTip to Pages, and then set true to IsOpen property.

<Page
    x:Class="WinUILab.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:controls="using:Microsoft.UI.Xaml.Controls"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:WinUILab"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:system="using:System"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    Loaded="Page_Loaded"
    mc:Ignorable="d">
    <Page.Resources>
        <controls:TeachingTip
            x:Name="teachingTip"
            Title="Do something button"
            ActionButtonContent="Don't show again."
            CloseButtonContent="Close"
            Subtitle="This is a button to do something."
            PreferredPlacement="Bottom"
            Target="{x:Bind buttonDoSomething}" />
        <controls:TeachingTip
            x:Name="teachingTipForApp"
            Title="About this app"
            Subtitle="This is for explain how to use TeachingTip control"
            PreferredPlacement="LeftTop">
            <controls:TeachingTip.HeroContent>
                <Image Source="Assets/StoreLogo.png" />
            </controls:TeachingTip.HeroContent>
        </controls:TeachingTip>
    </Page.Resources>
    <Grid>
        <Button
            x:Name="buttonDoSomething"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Click="Page_Loaded"
            Content="Do something" />

    </Grid>
</Page>
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

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

        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            teachingTip.IsOpen = true;
            teachingTipForApp.IsOpen = true;
        }
    }
}

When running the above code, then you will see following:

コメント 2019-05-24 154243.jpg

If you want to know about TeachingTip control more, then read following document.

https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/dialogs-and-flyouts/teaching-tip

 

Implicit Animations

Animations is really important to build great user experience. We can define implicit animations using XAML(not C# code).

Implicit Animations provides via Microsoft.Toolkit.Uwp.UI.Animations NuGet package.

 

We can animate controls using Implicit.ShowAnimations attached property, Implicit.HideAnimations attached property and Implicit.Animations attached property.

The following code is to animate Opacity property and Scale property of Border control, when the control Visibility is changed.

 

<Page
    x:Class="WinUILab.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:animations="using:Microsoft.Toolkit.Uwp.UI.Animations"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:extensions="using:Microsoft.Toolkit.Uwp.UI.Extensions"
    xmlns:local="using:WinUILab"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    mc:Ignorable="d">

    <Grid>
        <Button
            HorizontalAlignment="Stretch"
            VerticalAlignment="Top"
            Click="Button_Click"
            Content="Switch Visibility" />
        <Border
            x:Name="border"
            Width="100"
            Height="100"
            extensions:VisualExtensions.NormalizedCenterPoint="0.5,0.5,0"
            Background="Blue">
            <animations:Implicit.ShowAnimations>
                <animations:OpacityAnimation
                    From="0"
                    To="1"
                    Duration="0:0:5" />
                <animations:ScaleAnimation
                    From="0"
                    To="2"
                    Duration="0:0:5" />
            </animations:Implicit.ShowAnimations>
            <animations:Implicit.HideAnimations>
                <animations:OpacityAnimation
                    From="1"
                    To="0"
                    Duration="0:0:5" />
                <animations:ScaleAnimation
                    From="2"
                    To="0"
                    Duration="0:0:5" />
            </animations:Implicit.HideAnimations>
        </Border>
    </Grid>
</Page>

It's intuitive for XAML developers.

 

animations.gif

If you want to know more details, please see following document.

https://docs.microsoft.com/en-us/windows/communitytoolkit/animations/implicitanimations

 

Wrap up

Windows UI components have been improving to create great user experience app.

Some great features provides from OSS libraries like following:

Let's fun programming to create great Windows Desktop application!

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.