How to effectively use the ColorPicker control

27/11/2017 1 comment

ColorPicker is one of the easiest to use controls that comes with the Fall Creators Update. We just need to add it in the XAML to show a color picker that allows the user to browse through and select colors:

This kind of usage is straightforward, but typically we need to show the picker only when the user actually wants to select a color. So, we can for example insert the picker as a Flyout for a Button. But, suppose that we want to create a kind of classic UI in which we have a rectangle that, once clicked, opens the picker, and every color change will instantly update the rectangle background. How can we accomplish this?

First of all, we can define the ColorPicker as a Flyout for a Rectangle:

<Rectangle
    x:Name="ColorRectangle"
    Width="64" Height="64"
    Margin="20"
    Stroke="Black">
    <Rectangle.Fill>
        <SolidColorBrush Color="{x:Bind PopupColorPicker.Color, Mode=OneWay}" />
    </Rectangle.Fill>
    <FlyoutBase.AttachedFlyout>
        <Flyout>
            <ColorPicker
                x:Name="PopupColorPicker"
                ColorSpectrumShape="Ring"
                Color="White" />
        </Flyout>
    </FlyoutBase.AttachedFlyout>
</Rectangle>

Note that, at lines 6-8, we have bound the Fill property of the Rectangle to the Color property of the Picker. In this way, every change of the selected color will automatically reflect in the Rectangle background.

But an important thing is missing: since we are using the FlyoutBase.AttachedFlyout property, we need to manually open the Flyout, in this case when the user taps on the Rectangle. Let’s see how to do that using a behavior.

Let’s start by adding the Microsoft.Xml.Behavoirs.Uwp.Managed NuGet packages to the project. Then, we need to write the following declarations in the XAML page:

<Page
    ...
    xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
    xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
    >
    
    <Rectangle ...   
        ...
        <Interactivity:Interaction.Behaviors>
            <Core:EventTriggerBehavior EventName="Tapped">
                <local:OpenFlyoutAction />
            </Core:EventTriggerBehavior>
        </Interactivity:Interaction.Behaviors>
    </Rectangle>

We use an EventTriggerBehavoir for the Tapped event. When it occurs, we execute the OpenFlyoutAction, that is defined as follows:

public class OpenFlyoutAction : DependencyObject, IAction
{
    public object Execute(object sender, object parameter)
    {
        FlyoutBase.ShowAttachedFlyout((FrameworkElement)sender);
        return null;
    }
}

It simply opens the Flyout that is attached to the sender. We don’t need anything else: we can start the app, taps the Rectangle and try to select a color that will be instantly shown in the Rectangle itself.

You can download the app sample using the link below:
How to effectively use the ColorPicker control

Advertisements

The new PersonPicture control in the Fall Creators Update

08/11/2017 1 comment

PersonPicture is a simple yet powerful control that comes in the Universal Windows Platform with the Fall Creators Update. It allows to display the avatar image for a person, if one is available; if not, it displays the person’s initials or a generic glyph. It supports also showing an image, number or text as badge. It’s usage is straightforward. For example:

<StackPanel
    HorizontalAlignment="Center"
    VerticalAlignment="Center"
    Orientation="Horizontal">
    <PersonPicture
        x:Name="personPicture"
        Width="48"
        Height="48" />
    <TextBlock
        x:Name="nameTextBlock"
        Margin="5,0,0,0"
        VerticalAlignment="Center" />
</StackPanel>

In the OnNavigatedTo method, let’s add the following code to retrieve name and picture of the currently logged user:

protected override async void OnNavigatedTo(NavigationEventArgs e)
{
    var user = (await User.FindAllAsync(UserType.LocalUser, 
        UserAuthenticationStatus.LocallyAuthenticated)).FirstOrDefault();

    var firstName = (string)await user.GetPropertyAsync(
        KnownUserProperties.FirstName);
    var lastName = (string)await user.GetPropertyAsync(
        KnownUserProperties.LastName);
    var profileStream = await user.GetPictureAsync(UserPictureSize.Size64x64);

    personPicture.DisplayName = $"{firstName} {lastName}".Trim();

    if (profileStream != null)
    {
        var stream = await profileStream.OpenReadAsync();
        var bitmapImage = new BitmapImage();
        bitmapImage.SetSource(stream);
        personPicture.ProfilePicture = bitmapImage;
    }

    nameTextBlock.Text = personPicture.DisplayName;
}

To make this code work, we need to add the User Account Information capability in the app’s package manifest. After doing that, we’ll obtain something like that:

PersonPicture control showing profile image

PersonPicture control showing profile image

As we have set both the DisplayName and the ProfilePicture, the control shows the latter, because it has precedence over the other information. On the other hand, if we comment line 19, i.e. we do not set the ProfilePicture property, the result will be the following:

PersonPicture control showing profile initials

PersonPicture control showing profile initials

As we can see, the control automatically extracts the initials from the DisplayName property and shows them inside the control.

Beside that, we can directly bind the control to a Contact object that contains information about the person, by simply setting its Contact property.

If we want to show a badge on the image, for example a number, we just need to set the BadgeNumber property:

personPicture.BadgeNumber = 42;
PersonPicture control showing badge number

PersonPicture control showing badge number

To hide the badge after setting it, we need to set the BadgeNumber property to 0.

You can download the app sample using the link below:
The new PersonPicture control in the Fall Creators Update

Using SqlClient APIs and Dapper with Fall Creators Update SDK

25/10/2017 Leave a comment

SqlClient APIs, one of the most requested feature for UWP, have finally been added in the Fall Creators Update. Now we can connect to SQL Server directly from our apps, without the need of an external service, thanks to the System.Data.SqlClient namespace, in which we find familiar objects: SqlConnection, SqlCommand, SqlDataReader, etc.
Let’s see how to leverage these new APIs in a simple UWP app. First of all, we need to select Windows 10 Fall Creators Update as Target SDK:

Selecting Fall Creator Update as Target SDK

Selecting Fall Creator Update as Target SDK

In this way, we can now use the classic code we are used to:

using System.Data.SqlClient;

// ...

using (var conn = new SqlConnection(connectionString))
{
    using (var cmd = conn.CreateCommand())
    {
        cmd.CommandText = "<query>";

        using (var reader = await cmd.ExecuteReaderAsync())
        {
            while (reader.Read())
            {
                // ...
            }
        }
    }
}

Moreover, as we can use .NET Standard, we can take advantage of Dapper to greatly simply the data mapping. So, let’s add it via NuGet and try to build an app that access the following database schema (you can download it using the link at the end of the article):

The database schema for the UWP sample

The database schema for the UWP sample

Our app allows to search for characters that live in the specified city. So, first of all let’s create the POCO classes:

public class City
{
    public int Id { get; set; }

    public string Name { get; set; }
}

public class Character
{
    public int Id { get; set; }

    public string Name { get; set; }

    public DateTime FirstAppearance { get; set; }

    public string ImageUrl { get; set; }
}

And then let’s define the user interface in XAML:

<TextBox
    //... 
    x:Name="QueryTextBox"
    PlaceholderText="Search for names..." />
<ComboBox
    // ...
    x:Name="CitiesComboBox"    
    DisplayMemberPath="Name"
    SelectedValuePath="Id" />
<Button
    // ...
    x:Name="SearchButton"    
    Click="SearchButton_Click"
    Content="Search" />
<GridView
    //...
    x:Name="CharactersGridView">
    <GridView.ItemTemplate>
        <DataTemplate>
            <Grid Margin="0,0,0,10">
                <Image
                    Width="250"
                    Height="250"
                    Source="{Binding ImageUrl}"
                    Stretch="UniformToFill" />
                <Border VerticalAlignment="Bottom" Background="Gray">
                    <TextBlock
                        Margin="5,5,0,5"
                        Foreground="White"
                        Style="{ThemeResource BaseTextBlockStyle}"
                        Text="{Binding Name}" />
                </Border>
            </Grid>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

At startup, we have to load all the cities and bind them to the CitiesComboBox element:

protected override async void OnNavigatedTo(NavigationEventArgs e)
{
    var cities = await GetCitiesAsync();
    CitiesComboBox.ItemsSource = cities;
    CitiesComboBox.SelectedIndex = 0;

    base.OnNavigatedTo(e);
}

public async Task<IEnumerable<City>> GetCitiesAsync()
{
    using (var conn = new SqlConnection(connectionString))
    {
        var cities = await conn.QueryAsync<City>(
            @"SELECT c.CityId As Id, c.Name
            FROM Cities c
            ORDER BY c.Name");

        return cities;
    }
}

In the GetCitiesAsync method (lines 10-21), we first create the SqlConnection, then we use the QueryAsync extension method from Dapper (lines 14-17), that executes the query against the database and retrieves the results as an IEnumerable collection of City, performing a binding based on column names.

When the user presses the Search button, we need to start the actual search:

private async void SearchButton_Click(object sender, RoutedEventArgs e)
{
    var characters = await GetCharactersAsync(QueryTextBox.Text,
        Convert.ToInt32(CitiesComboBox.SelectedValue));

    CharactersGridView.ItemsSource = characters;
}

public async Task<IEnumerable<Character>> GetCharactersAsync(string name,
    int cityId)
{
    using (var conn = new SqlConnection(connectionString))
    {
        var characters = await conn.QueryAsync<Character>(
            @"SELECT c.CharacterId As Id, c.Name, c.FirstAppearance, c.ImageUrl
            FROM Characters c
            WHERE c.Name LIKE @name
            AND c.CityId = @cityId
            ORDER BY c.Name",
            new
            {
                Name = $"%{name}%",
                CityId = cityId
            });

        return characters;
    }
}

The GetCharactersAsync method at lines 9-28 takes name and cityId as arguments and uses them to build the query: it is a standard SQL query (as above), but in this case we have also two parameters with the @ symbol (lines 17-18). We specify them using an anonymous class that has properties with the same case-insentive names as the parameters (lines 20-24). Dapper will create the corresponding SqlParameter objects and passes them to the query engine.

In conclusion, running the app we should see something like that:

Using SqlClient APIs with UWP

Using SqlClient APIs with UWP

Keep in mind that we can’t use LocalDB when connecting from a UWP app, otherwise we’ll get a PlatformNotSupportedException error. So we must use SQL Server, SQL Server Express or SQL Azure.

You can download the app sample, with the database script, using the link below:
Using SqlClient APIs and Dapper with Fall Creators Update SDK

Custom Vision Companion on ioProgrammo

20/10/2017 Leave a comment

I have written a new article for the n°219 of ioProgrammo (November 2017). I talk about Custom Vision Service and show how to build a Universal Windows Platform app that uses these APIs to get predictions from images and photos taken in the real world.

ioProgrammo n°219 (November 2017)

ioProgrammo n°219 (November 2017)

The app described in the article, Custom Vision Companion, is open source and is available on GitHub.

How to handle navigation events in MVVM using Windows Template Studio

17/10/2017 1 comment

Windows Template Studio is a Visual Studio 2017 Extension that accelerates the creation of new Universal Windows Platform (UWP) apps using a wizard-based experience.
Among the other things, it allows to use the MVVM pattern with a simple selection in the wizard, by providing a basic implementation rather than using MVVM Light. This approach avoids writing a lot of boilerplate code, but if we choose it, we’ll discover that an important feature is currently missing: the ability to automatically calls methods on ViewModels when we navigate to/from a Page.
However, adding this behavior is quite simple. We just need to add an INavigable interface to the project:

public interface INavigable
{
    Task OnNavigatedToAsync(object parameter, NavigationMode mode);

    void OnNavigatingFrom(NavigatingCancelEventArgs e);

    void OnNavigatedFrom();
}

Then, we have to edit the NavigationServices.Ex class, that is placed in the Services folder. First of all, we need to add the registration/deregistration methods for the Frame.Navigating event in the RegisterFrameEvents and UnregisterFrameEvents methods:

private void RegisterFrameEvents()
{
    if (_frame != null)
    {
        _frame.Navigating += Frame_Navigating;
        _frame.Navigated += Frame_Navigated;
        _frame.NavigationFailed += Frame_NavigationFailed;
    }
}

private void UnregisterFrameEvents()
{
    if (_frame != null)
    {
        _frame.Navigating -= Frame_Navigating;
        _frame.Navigated -= Frame_Navigated;
        _frame.NavigationFailed -= Frame_NavigationFailed;
    }
}

Then, let’s add the Frame_Navigating event handler and modify the existing Frame_Navigated as follows:

private void Frame_Navigating(object sender, NavigatingCancelEventArgs e)
{
    var dataContext = ResolveForPage(Frame.Content as Page);
    if (dataContext != null)
    {
        dataContext.OnNavigatingFrom(e);
        if (!e.Cancel)
        {
            dataContext.OnNavigatedFrom();
        }
    }
}

private async void Frame_Navigated(object sender, NavigationEventArgs e)
{
    Navigated?.Invoke(sender, e);

    var dataContext = ResolveForPage(e.Content as Page);
    if (dataContext != null)
    {
        await dataContext.OnNavigatedToAsync(e.Parameter, e.NavigationMode)
            .ConfigureAwait(false);
    }
}

private INavigable ResolveForPage(Page page)
    => (page?.DataContext as INavigable);

In the first event, if the DataContext (i.e., the ViewModel) of the Page implements the INavigable interface, we call its OnNavigatingFrom method, passing the NavigatingCancelEventArgs to it. So, if we set its Cancel property to true, we can cancel the navigation back. Otherwise, we then call the OnNavigatedFrom method.
On the other hand, when we navigate to a page, the Frame_Navigated event handler is invoked. In this case, we try to call the OnNavigateToAsync method, passing parameters and NavigationMode to it.

Now everything is ready. We can for example write something like this:

public class MainViewModel : ViewModelBase, INavigable
{
    // ...

    public Task OnNavigatedToAsync(object parameter, NavigationMode mode)
    {
        return Task.CompletedTask;
    }

    public void OnNavigatingFrom(NavigatingCancelEventArgs e)
    {
    }

    public void OnNavigatedFrom()
    {
    }
}

We don’t need anything else. We can simply set breakpoints on these methods and see that they are invoked when we navigate to/from the corresponding page. Of course, we can define our own ViewModelBase class that already implements the INavigable interface, so we have to override only the navigation methods we really need.

Real-time voice translation with Microsoft Translator on ioProgrammo

26/06/2017 1 comment

I have written a new article for the n°215 of ioProgrammo (July 2017). This time I show how to use Microsoft Translator Speech API to build a real-time voice translation app for the Universal Windows Platform.

ioProgrammo July 2017

ioProgrammo July 2017

Here it is a short video showing the project that comes with the article:

Two hidden gems in the Universal Windows Platform

22/05/2017 2 comments

Even if the Creators Update version of Windows 10 has been released a couple of month ago and we’re waiting for the next Fall Creators Update, there is still room to talk about the Anniversary Edition, because it contains a couple of gems that not many people know about.

Raise your hand if you never had a BooleanToVisibilityConverter class in any of your apps. It is necessary because the Visibility property of UIElement is an Enum, but tipically, in particular when we’re following the MVVM pattern, we just have a Boolean property that we want to use to control the visibility of an object. In this case, we could add a BooleanToVisibilityConverter class to our app, like the following one:

public sealed class BooleanToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, 
        string language)
    {
        return (value is bool && (bool)value) 
            ? Visibility.Visible : Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, 
        string language)
    {
        return value is Visibility && (Visibility)value == Visibility.Visible;
    }
}

Of course, there could be other implementations, or we could use an attached property instead of a Converter, but the scenario remains the same.

Starting from Windows 10, version 1607 (i.e., the Anniversary Edition) this is no longer necessary. In fact, if we use the {x:Bind} markup extension (that was first introduced in the initial release of Windows 10), we can cast a Boolean property to a Visibility value directly in the XAML defition:

<Image Source="Assets/Favorite.png" 
       Visibility="{x:Bind (Visibility)ViewModel.IsFavorited}" />

The meaning of this declaration is straightforward: if ViewModel.IsFavorited is true, it returns Visibility.Visible, otherwise Visibility.Collapsed. In this way, we do not need any extra class anymore.

But there is another cool feature that helps us solving a common problem. If we’re developing a “chat-like” app, we tipically have a ListView in which we add items to the bottom. In this scenario, we often have the requirement to automatically scroll the ListView as new items are inserted, so that the last ones are always visible. To obtain this, we could add a ScroolToBottom Behavior class to our app.

Again, with the Anniversary Edition we can set the ItemsUpdatingScrollMode property of the ItemsStackPanel to KeepLastItemInView, that adjusts the scroll offset to keep the last visible item showing at the bottom of the view. In other words, we just need to set the ItemsPanelTemplate of the ListView in this way:

<ListView ItemsSource="{x:Bind ViewModel.Samples}">
    ...
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <ItemsStackPanel ItemsUpdatingScrollMode="KeepLastItemInView" />
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
</ListView>

And the list will automatically scroll to bottom as new items are added to it. No code at all is needed to implement this behavior.

You can download a sample of these features using the link below:
Anniversay Update Cool Features