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

Pay attention to .NET Native when using Reflection (MVVM scenario)

22/02/2016 Comments off

Among the other things, .NET Native tries to reduce the app size by analyzing the code and striping out unused .NET objects. This approach works very well, but we need to pay attention when we you work with Reflection, because in this case we must explicitly tell to .NET Native which elements are available for it.

A particular scenario occurs if we’re following the MVVM pattern and we have a classic app with a GridView or a ListView and we want to invoke a command when the user clicks an item, passing the item itself to the command. With the Universal Windows Platform, this task can be accomplished using an EventTriggerBehavoir form XamlBehavoirs along with an InvokeCommandAction and an InputConverter:

<GridView IsItemClickEnabled="True" ItemsSource="{Binding People}">
    <GridView.ItemTemplate>
        <DataTemplate>
            ...
        </DataTemplate>
    </GridView.ItemTemplate>

    <Interactivity:Interaction.Behaviors>
        <Interactions:EventTriggerBehavior EventName="ItemClick">
            <Interactions:InvokeCommandAction 
                Command="{Binding ItemSelectedCommand}" 
                InputConverter="{StaticResource EventArgsConverter}" 
                InputConverterParameter="ClickedItem" />
        </Interactions:EventTriggerBehavior>
    </Interactivity:Interaction.Behaviors>
</GridView>

At lines 9-14 we use an EventTriggerBehavior to catch the ItemClick event of the GridView and execute in response the ItemSelectedCommand action of the ViewModel. Thanks to InputConverter and InputConverterParamter (lines 12-13), this action automatically receives the clicked item as argument:

public sealed class EventArgsConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, 
        string language)
    {
        if (value != null)
        {
            var propertyPath = parameter as string;
            if (!string.IsNullOrWhiteSpace(propertyPath))
            {
                var propertyPathParts = propertyPath.Split('.');
                object propertyValue = value;
                foreach (var propertyPathPart in propertyPathParts)
                {
                    var propInfo = propertyValue.GetType().GetTypeInfo().
                        GetDeclaredProperty(propertyPathPart);

                    propertyValue = propInfo.GetValue(propertyValue);
                }

                return propertyValue;
            }
        }

        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, 
        string language)
    {
        throw new NotImplementedException();
    }
}

This Converter extracts the property name of the event argument that is passed as parameter (line 8, in this case ClickedItem) and then uses Reflection (lines 15-18) to get the actual value that will be received by the command.

This code works without problem in Debug mode, but when we switch to Release, enabling the .NET Native toolchain (that is required for app submission), if we click an item on the grid we’ll get a runtime error like the following one:

Unhandled exception at 0x77026D7E (combase.dll)

This occurs because the .NET Native toolchain has removed the ItemClickEventArgs class from the compiled code, as it hasn’t found any reference to it in the code, because it is accessed only at runtime through Reflection.

So, as said at the beginning we need to tell to .NET Native to keep this type during compilation. Let’s open the file Default.rd.xml inside the project Properties folder: it contains the Runtime Directives for .NET Native. All that we need is to add a declaration for the ItemClickEventArgs type:

<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
    <Application>
        <!--
          An Assembly element with Name="*Application*" applies to all 
          assemblies in the application package. The asterisks are not 
          wildcards.
        -->
        
        <Assembly Name="*Application*" Dynamic="Required All" />

        <!-- Add your application specific runtime directives here. -->
        <Type Name="Windows.UI.Xaml.Controls.ItemClickEventArgs" 
              Dynamic="Required Public" />

    </Application>
</Directives>

At lines 12-13 we have specified that we want to keep the ItemClickEventArgs type in compilation, even if it isn’t statically referenced in the code. Now we can compile the app in Release mode again: this time everything will work as expected.

We can refer to MSDN documentation to get more information about the Runtime Directives Configuration File.

Using MVVM Light ViewModelBase class with Template 10

25/01/2016 1 comment

Template10 comes with a handful ViewModelBase class that provides an easy way to handle events such as OnNavigatedTo, OnNavigatingFrom, access the Navigation Service from View Models and so on. In the previous posts we have seen how to integrate this class with MVVM Light, but what if we already have View Models that inherit from MVVM Light ViewModelBase, or as usually happens we have our ViewModelBase class, that in turns inherits from MVVM Light one?

If our View Models directly inherit from MVVM Light ViewModelBase class, we simply need to implement the Template 10 INavigable interface:

public class MainViewModel : GalaSoft.MvvmLight.ViewModelBase,
    Template10.Services.NavigationService.INavigable
{
    public Task OnNavigatedToAsync(object parameter, NavigationMode mode, 
        IDictionary<string, object> state)
    {
        // ...
        return Task.CompletedTask;
    }

    public Task OnNavigatedFromAsync(IDictionary<string, object> state, 
        bool suspending)
    {
        // ...
        return Task.CompletedTask;
    }

    public Task OnNavigatingFromAsync(NavigatingEventArgs args)
    {
        // ...
        return Task.CompletedTask;
    }

    [JsonIgnore]
    public IDispatcherWrapper Dispatcher { get; set; }

    [JsonIgnore]
    public INavigationService NavigationService { get; set; }

    [JsonIgnore]
    public IStateItems SessionState { get; set; }
}

In this case the recommended approach is of course to create a base class that inherits from MVVM Light ViewModelBase class and implements the Template 10 INavigable interface:

public abstract class MyViewModelBase : GalaSoft.MvvmLight.ViewModelBase,
    Template10.Services.NavigationService.INavigable
{
    public virtual Task OnNavigatedToAsync(object parameter, 
        NavigationMode mode, IDictionary<string, object> state) 
        => Task.CompletedTask;

    public virtual Task OnNavigatedFromAsync(IDictionary<string, object> state,
        bool suspending) 
        => Task.CompletedTask;

    public virtual Task OnNavigatingFromAsync(NavigatingEventArgs args)
        => Task.CompletedTask;

    [JsonIgnore]
    public IDispatcherWrapper Dispatcher { get; set; }

    [JsonIgnore]
    public INavigationService NavigationService { get; set; }

    [JsonIgnore]
    public IStateItems SessionState { get; set; }
}

As said before, if we already have our custom ViewModelBase class, we just need to make it implement the INavigable interface in the same way. In any cases, after defining this class, we can use it as usual:

public class MainViewModel : MyViewModelBase
{
    private string name;
    public string Name
    {
        get { return name; }
        set { base.Set(ref name, value, broadcast: true); }
    }

    public override Task OnNavigatedToAsync(object parameter,
        NavigationMode mode, IDictionary<string, object> state)
    {
        var argument = parameter?.ToString();

        if (state.Any())
        {
            //...

            state.Clear();

        }

        // Calls a method from MVVM Light ViewModelBase class.
        base.Broadcast(null, "Marco", nameof(Name));

        return base.OnNavigatedToAsync(parameter, mode, state);
    }
}

We can now access all the features provided by either MVVM Light and Template 10 without further code refactoring.

Using MVVM Light Messenger with Template 10

30/11/2015 1 comment

In previous posts we shown how to integrate MVVM Light with Template 10. We still need to talk about an important component of the toolkit, the Messenger. It allows for communication within the application, i.e. between View Models, Views and View Models, and so on.

We can access the Messenger from anywhere in our code, using its static Messenger.Default property. So, for example, we can easily integrate it in a View Model even if it inherits from the Template 10 ViewModelBase class (instead of the MVVM Light base class).

The first thing we can do with the Messenger is sending object, i.e. to execute code in the View Model in response to View event handlers:

private void GridView_ItemClick(object sender, ItemClickEventArgs e)
{
    // Sends a message with a Person object.
    var person = e.ClickedItem as Person;
    Messenger.Default.Send(person);
}

// In the View Model...
// Registers for incoming Person messages.
Messenger.Default.Register<Person>(this, (p) =>
{
    // Works with the Person object.
});

MVVM Light provides also a built-in class, NotificationMessage, that we can use if we just want to send string messages:

// Sends a notification message with a string content.
Messenger.Default.Send(new NotificationMessage("CloseApp"));

// Registers for incoming Notification messages.
Messenger.Default.Register<NotificationMessage>(this, (message) =>
{
    // Checks the actual notification.
    switch (message.Notification)
    {
        case "CloseApp":
            break;

        default:
            break;
    }
});

At lines 8-15, we check the Notification property to determine the specific message that has been sent. Of course, we can use constants to avoid the repetition of string values.

We can combine both of these scenarios and use the generic version of NotificationMessage to send an object along with a string message, which for example specifies the action that we want to perform:

private void GridView_ItemClick(object sender, ItemClickEventArgs e)
{
    // Sends a message with a Person object.
    var person = e.ClickedItem as Person;

    // Sends a notification message with a Person as content.
    Messenger.Default.Send(new NotificationMessage<Person>(person, "Select"));
    //Messenger.Default.Send(new NotificationMessage<Person>(person, "Update"));
}

// In the View Model...
// Registers for incoming Notification messages.
Messenger.Default.Register<NotificationMessage<Person>>(this, (message) =>
{
    // Gets the Person object.
    var person = message.Content;

    // Checks the associated action.
    switch (message.Notification)
    {
        case "Select":
            break;

        case "Update":
            break;

        default:
            break;
    }
});

The generic version of NotificationMessage exposes a Content property (line 16) that contains the actual object. So we can retrieve it and use the Notification value to determine which action to execute (lines 19-29).

In some cases, we would need to execute an action back on the sender when the message is received. For these scenarios, MVVM Light provides the NotificationMessageAction class, which allows to specify a callback method that can be executed by the recipient to notify the sender that the message has been processed. With this object, however, we can only send a notification string message. So what about if we want to send also a content class, like in the generic NotificationMessage?

First of all, we need to define a class that inherits from the standard NotificationMessageAction class:

public class NotificationMessageAction<T, TCallbackParameter> 
    : NotificationMessageAction<TCallbackParameter>
{
    public T Content { get; }

    public NotificationMessageAction(T content, string notification, 
        Action<TCallbackParameter> callback)
      : base(notification, callback)
    {
        Content = content;
    }
}

Basically, we have added the generic Content property (line 4). Then, we can write something like this:

private void GridView_ItemClick(object sender, ItemClickEventArgs e)
{
    // Sends a message with a Person object.
    var person = e.ClickedItem as Person;

    // Sends a notification message with a Person as content, 
    // a string message and a callback to be executed at the end.
    Messenger.Default.Send(new NotificationMessageAction<Person, int>(person, 
        "Update", (response) => 
    {
        // "response" contains the response (int in this example) from the
        // receiver.
    }));
}

// In the View Model...
// Registers for incoming NotificationMessageAction messages.
Messenger.Default.Register<NotificationMessageAction<Person, int>>(this, 
    (message) =>
{
    // Gets the Person object.
    var person = message.Content;

    // Checks the associated action.
    switch (message.Notification)
    {
        case "Update":
            break;

        default:
            break;
    }

    // Executes the callback.
    message.Execute(42);
});

At lines 8-13 we send our NotificationMessageAction message, specifying that Content is a Person and the callback parameter is int. Then, in the View Model we process the message as we did in the previous example (lines 21-32) and finally we execute the callback (line 35): this instruction will cause the action defined at lines 10-13 to be executed.

If we use an IoC Container for View Models (like MVVM Light SimpleIoC), we must remember that Messenger registrations remain active even if we change View (because View Models actually stay in memory), so they always receive notifications. Instead, we usually want that a View Model receives notification only if its corresponding View is active.

To overcome this problem, we simply can register messages in the Template 10 OnNavigatedTo method and unregister them in OnNavigatedFromAsync:

public override void OnNavigatedTo(object parameter, NavigationMode mode,
    IDictionary<string, object> state)
{
    // Registers for incoming Person messages.
    Messenger.Default.Register<Person>(this, (p) =>
    {
        
    });

    base.OnNavigatedTo(parameter, mode, state);
}

public override Task OnNavigatedFromAsync(IDictionary<string, object> state, 
    bool suspending)
{
    // Unregisters all messages registered by this receiver.
    Messenger.Default.Unregister(this);

    return base.OnNavigatedFromAsync(state, suspending);
}

To unregister a messenger recipient completely, we simply need to call the Unregister method, passing the receiver reference (line 17).