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

Microsoft Translator Service on ioProgrammo

16/02/2017 2 comments

I have written a new article for the n°211 of ioProgrammo (February/March 2017). This time I introduce my Translator Service Library and show how to use it to build a chat with real-time translation capabilities.

ioProgrammo February/March 2017

ioProgrammo February/March 2017

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

How to shutdown a Windows 10 IoT Core device from a UWP app

13/12/2016 1 comment

When dealing with an embedded device, we may have the need to turn it off. The same is true for Windows 10 IoT Core devices: in fact, the DefaultApp and the Device Portal have an option that allows to shutdown or restart the board. So, if we deploy our app, how can we implement this feature?

First of all, we need to add the Windows IoT Extensions for the UWP to our project:

Windows IoT Extensions for the UWP

Windows IoT Extensions for the UWP

In this way, we have access to the Windows.System.ShutdownManager class, that we can use to manage the shutdown of devices. It exposes two static methods:

So, for example:

// Shutdowns the device immediately:
ShutdownManager.BeginShutdown(ShutdownKind.Shutdown, TimeSpan.FromSeconds(0));

// Restarts the device within 5 seconds:
ShutdownManager.BeginShutdown(ShutdownKind.Restart, TimeSpan.FromSeconds(5));

In order for this code to work properly, we need also to give an extra capability to our app. Let’s open the Package.appxmanifest file with the Visual Studio XML Editor and add or update the following values:

<Package
         ...
         xmlns:iot="http://schemas.microsoft.com/appx/manifest/iot/windows10"
         IgnorableNamespaces="uap mp iot">
  
  <Capabilities>
    ...
    <iot:Capability Name="systemManagement" />
  </Capabilities>
</Package>

If we don’t set this capability, we’ll get an UnauthorizedAccessException error when calling ShutdownManager methods.Beg

Xamarin.Forms and Azure Mobile apps on ioProgrammo

08/09/2016 1 comment

I have written a new article for the n°206 of ioProgrammo (September 2016). This time I talk about Xamarin.Forms and how to use it together with Azure Mobile apps in order to create an app that is strictly integrated with Facebook.

ioProgrammo September 2016

ioProgrammo September 2016

Categories: .NET, Azure, C#, General, Xamarin

A simple NavigationService for Xamarin.Forms

11/07/2016 1 comment

If we do a search on the Internet, we’ll find a lot of implementations of a NavigationService for Xamarin.Forms. While all of them are surely valid, there are two things that I don’t like much:

  • if we want to pass arguments to the new page, we need to use the constructor of the page itself (i.e., adding an object parameter to it);
  • they don’t provide a convenient way to clear navigation history, that is often a requirement (i.e., after login/registration).

So, I ended up writing my own implementation. It is very simple and doesn’t cover all the scenarios, but at this moment it completely satifies my need:

public class NavigationService
{
    private Dictionary<string, Type> pages { get; }
        = new Dictionary<string, Type>();

    public Page MainPage => Application.Current.MainPage;

    public void Configure(string key, Type pageType) => pages[key] = pageType;

    public void GoBack() => MainPage.Navigation.PopAsync();

    public void NavigateTo(string pageKey, object parameter = null,
        HistoryBehavior historyBehavior = HistoryBehavior.Default)
    {
        Type pageType;
        if (pages.TryGetValue(pageKey, out pageType))
        {
            var displayPage = (Page)Activator.CreateInstance(pageType);
            displayPage.SetNavigationArgs(parameter);

            if (historyBehavior == HistoryBehavior.ClearHistory)
            {
                MainPage.Navigation.InsertPageBefore(displayPage,
                    MainPage.Navigation.NavigationStack[0]);

                var existingPages = MainPage.Navigation.NavigationStack.ToList();
                for (int i = 1; i < existingPages.Count; i++)
                    MainPage.Navigation.RemovePage(existingPages[i]);
            }
            else
            {
                MainPage.Navigation.PushAsync(displayPage);
            }
        }
        else
        {
            throw new ArgumentException($"No such page: {pageKey}.",
                nameof(pageKey));
        }
    }
}

public enum HistoryBehavior
{
    Default,
    ClearHistory
}

public static class NavigationExtensions
{
    private static ConditionalWeakTable<Page, object> arguments
        = new ConditionalWeakTable<Page, object>();

    public static object GetNavigationArgs(this Page page)
    {
        object argument = null;
        arguments.TryGetValue(page, out argument);

        return argument;
    }

    public static void SetNavigationArgs(this Page page, object args)
        => arguments.Add(page, args);
}

The idea of this NavigationService is to first register all the pages using the Configure method (line 8), just like the MVVM Light approach. The core of the implementation is the NavigateTo method (lines 12-41). It tries to get the page type corresponding the passed key (line 16) and then instantiate it using Activator.CreateInstance.

This is the first difference with other solutions: we create the page using its default parameterless constructor. The actual parameter, if any, is stored in a kind of Dictionary using the SetNavigationArgs extension method at line 19 (its implementation is at lines 62-63).

Then, we check whether we want to clear history after navigation: if this case, we insert the new page before the current one (lines 23-24) and then, at lines 26-28, we remove all the other pages from the stack. Otherwise, at line 32 we just perform a normal PushAsync of the page.

Let’s see how to use it. First of all, we configure the NavigationService in the App class:

public partial class App : Application
{
    public static NavigationService NavigationService { get; }
        = new NavigationService();

    public App()
    {
        InitializeComponent();

        NavigationService.Configure("MainPage", typeof(MainPage));
        NavigationService.Configure("SecondPage", typeof(SecondPage));
        NavigationService.Configure("ThirdPage", typeof(ThirdPage));

        MainPage = new NavigationPage(new MainPage());
    }
}

Then, in MainPage.xaml we write something like this:

<StackLayout Margin="12" HorizontalOptions="Center">
  <Entry x:Name="arguments" Placeholder="Arguments..." />
  <StackLayout Orientation="Horizontal" Spacing="0">
    <Label Text="Clear History" VerticalOptions="Center" Margin="0,0,10,0" />
    <Switch x:Name="clearHistory" VerticalOptions="Center" />
  </StackLayout>
  <Button x:Name="navigate" Text="Go to second page" Clicked="navigate_Clicked" />
</StackLayout>

So we have an Entry that allows to specify arguments to be passed to the target (line 2), a Switch to clear history after navigation (line 5) and a Button to actually go to the second page (line 7). The corresponding code-behind follows:

private void navigate_Clicked(object sender, EventArgs e)
{
    var historyBehavior = clearHistory.IsToggled
        ? HistoryBehavior.ClearHistory : HistoryBehavior.Default;

    App.NavigationService.NavigateTo("SecondPage", arguments.Text, 
        historyBehavior);
}

We simply get the HistoryBehavior based on Switch value and then we pass it along with the target page and the arguments to the NavigateTo method. Finally, in the Second Page we override the OnAppearing method:

protected override void OnAppearing()
{
    var args = this.GetNavigationArgs();
    passedArguments.Text = $"Passed arguments: {args}";

    base.OnAppearing();
}

Using the GetNavigationArgs extension method, at line 3 we retrieve the arguments we have specified with NavigateTo.

Another interesting point about this solution is that it can easily be integrated with an MVVM approach, but we’ll go deeper in this argument in a future post.

You can download the complete example using the link below:
A simple NavigationService for Xamarin.Forms

Categories: C#, Xamarin

A Behavior for CameraPressed event in Universal Windows apps

30/05/2016 1 comment

If we’re developing a Universal app that uses the camera, on Windows Mobile we may want to use the hardware camera button for example to take a photo. Of course, we need to take into account that on desktops and tablets we don’t have this feature. To add a bit more complexity, suppose we’re following the MVVM pattern. So, how can we manage this scenario?

In order to handle the hardware camera button, we just need a reference to the Windows Mobile Extensions for the UWP. In this way, we obtain access to Mobile specific features:

Windows Mobile Extensions for the UWP

Windows Mobile Extensions for the UWP

As we’re working with MVVM, the best solution is to create a custom Behavior. First of all, let’s add its reference through NuGet, searching for the package Microsoft.Xaml.Behaviors.Uwp.Managed:

UWP Behavoirs package on NuGet

UWP Behavoirs package on NuGet

Now we have all the prerequisites to create the CameraPressedBehavior:

[ContentProperty(Name = "Actions")]
public sealed class CameraPressedBehavior : Behavior
{
    public static readonly DependencyProperty ActionsProperty = 
        DependencyProperty.Register(
        "Actions",
        typeof(ActionCollection),
        typeof(CameraPressedBehavior),
        new PropertyMetadata(null));

    public ActionCollection Actions
    {
        get
        {
            var actionCollection = (ActionCollection)
                this.GetValue(ActionsProperty);

            if (actionCollection == null)
            {
                actionCollection = new ActionCollection();
                this.SetValue(ActionsProperty, actionCollection);
            }

            return actionCollection;
        }
    }

    [System.Runtime.CompilerServices.PlatformSpecific]
    private readonly bool isTypePresent;

    public CameraPressedBehavior()
    {
        isTypePresent = 
            Windows.Foundation.Metadata.ApiInformation.IsTypePresent(
                "Windows.Phone.UI.Input.HardwareButtons");
    }

    protected override void OnAttached()
    {
        base.OnAttached();

        if (isTypePresent)
            HardwareButtons.CameraPressed += HardwareButtons_CameraPressed;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();

        if (isTypePresent)
            HardwareButtons.CameraPressed -= HardwareButtons_CameraPressed;
    }

    private void HardwareButtons_CameraPressed(object sender, CameraEventArgs e)
    {
        Interaction.ExecuteActions(AssociatedObject, Actions, EventArgs.Empty);
    }       
}

At lines 4-26 we define the Actions dependency property that stores the action to be executed when then button is pressed. This part of code is usually present in every behavior.

Then, in the Behavior costructor (lines 31-36), we use the ApiInformation.IsTypePresent method to check whether the Windows.Phone.UI.Input.HardwareButtons type is actually present, i.e. if the platform provides access to hardware buttons. If this is the case, in the OnAttached method (lines 38-44) we register for the CameraPressed event, otherwise we do nothing. In the same way, in the OnDetaching method we remove the event registration, if necessary. Thanks to these checks, the code can safely be executed also on platforms that don’t have hardware buttons.

Finally, in the CameraPressed event handler (lines 54-57), we call the Interaction.ExecuteActions static method, that in turn executes all the registered actions.

Now we can use the Behavior in our XAML page. For example:

<Page
    ...
    xmlns:Interactivity="using:Microsoft.Xaml.Interactivity" 
    xmlns:Interactions="using:Microsoft.Xaml.Interactions.Core"
    xmlns:behaviors="using:See4Me.Behaviors"
    ...>

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        ...
        <Interactivity:Interaction.Behaviors>
            <behaviors:CameraPressedBehavior>
                <Interactions:InvokeCommandAction 
                              Command="{Binding TakePhotoCommand}"  />
            </behaviors:CameraPressedBehavior>            
        </Interactivity:Interaction.Behaviors>
    </Grid>
</Page>

We add the CameraPressedBehavoir to the page (lines 10-15) so that, when the button is pressed, the InvokeCommandAction is executed, causing the TakePhotoCommand to be run. As said before, this behavior on desktops and tables has no effects, so it actually works only on phones.

Clear history in Xamarin Android with MVVM Light NavigationService

14/03/2016 Comments off

If we’re working with Xamarin, MVVM Light provides quite useful helpers (derived from the Windows implementation) that simplify a lot our work. Among the others, we have a INavigationService class that abstracts the concept of starting a new Activity (Android) rather than activating a certain Controller (iOS), providing a unique approach to page navigation.

This approach is general and the interface is the same on all the platforms. While this helps having a common navigation system, it can leads to platform specific problem. Imagine we are on Android and we need to delete history (for example, after a login). On this platform, navigation history can be deleted only in conjunction with the start of an Activity (i.e., we need to tell Android to delete any existing task before starting the Activity). But if we’re using INavigationService, we have a NavigateTo method to which we can pass only the pageKey and an optional object that will be received by the new activity. We haven’t control on how the new activity is started. So, how can we delete history?

We can tweak the original NavigationService implementation for Android to handle this scenario. First of all, we need to define a NavigationParameter class:

public class NavigationParameter
{
    public ActivityFlags? Flags { get; }

    public object Content { get; }

    public NavigationParameter(ActivityFlags? flags = null)
    {
        Flags = flags;
    }

    public NavigationParameter(object content, ActivityFlags? flags = null)
    {
        Content = content;
        Flags = flags;
    }
}

It allows us to pass custom activation flags rather the a single object to the NavigateTo method. To use this class, a little modification to NavigationService.cs file is requested. Let’s get the original implementation from CodePlex. Then, locate the following code in the NavigateTo(string pageKey, object parameter) method:

if (parameter != null)
{
    lock (_parametersByKey)
    {
        // ...
    }
}

We need to replace it with the following code:

if (parameter != null)
{
    lock (_parametersByKey)
    {
        var guid = Guid.NewGuid().ToString();

        var flags = (parameter as NavigationParameter)?.Flags;
        var actualParameter = (parameter as NavigationParameter)?.Content 
            ?? parameter;

        _parametersByKey.Add(guid, actualParameter);
        intent.PutExtra(ParameterKeyName, guid);

        if (flags.HasValue)
            intent.SetFlags(flags.Value);
    }
}

The core of the change is at lines 7-9. We check if parameter is a NavigationParameter: in this case, we extract the activation flags and the actual parameter; otherwise, we assume we don’t have any activation flag and that the actual parameter is the parameter argument itself. So, we can continue to use the NavigateTo method in the usual way (no breaking changes). Then, at lines 14-15, if flags has value, we pass it to the Intent.SetFlags method.

So, when we need to clear history, we just need to create a NavigationParameter with the correct activation flags, like in the following example:

private NavigationParameter CreateParameter<T>(T parameter, bool clearHistory)
{
    var flags = clearHistory ? (ActivityFlags.NewTask | ActivityFlags.ClearTask) 
        : default(ActivityFlags);
    var args = new NavigationParameter(parameter, flags);

    return args;
}
        
private void NavigateToHomePage<T>(T parameter)
{
    var args = this.CreateParameter(parameter, clearHistory: true);
    navigationService.NavigateTo(Constants.HomePage, args);
}

Note that, as we use NavigationParamenter only to pass activation flags and the new activity receives always the actual parameter, the GetAndRemoveParameter(Intent) method will keep working in the usual way. Moreover, as already said, we can continue to use NavigateTo method as before if we don’t need to clear history.

Categories: C#, MVVM, Xamarin