Android

Xamarin Forms, the MVVMLight Toolkit and I: showing dialog messages

Xamarin Forms, the MVVMLight Toolkit and I: showing dialog messages

In this post, I will show you how to display dialog messages (also known as message box). This time, we will use again native implementations (like in the second post about Dependency Injection) to get the job done. I could have used the Xamarin.Forms Page.DisplayAlertmethod, but that one does not allow a lot of customization, so I went down to implement it my way.

Like always, the interface dictates functionality

Because of the Xamarin Forms code being a portable class library, we need an new interface that can be called from all three platforms. I am covering four scenarios which I use frequently in my apps:

public interface IDialogService
{
    void CloseAllDialogs();

    Task ShowMessageAsync(string title, string message);

    Task ShowErrorAsync(string title, Exception error, string buttonText, Action<bool> closeAction, bool cancelableOnTouchOutside = false, bool cancelable = false);

    Task ShowMessageAsync(string title, string message, string buttonText, Action<bool> closeAction, bool cancelableOnTouchOutside = false, bool cancelable = false);

    Task ShowMessageAsync(string title, string message, string buttonConfirmText, string buttonCancelText, Action<bool> closeAction, bool cancelableOnTouchOutside = false, bool cancelable = false);
}

Of course, I want to display those message dialogs asynchronously, that’s why I wrap them in a Task. Let’s have a look into the implementation:

Android

List<AlertDialog> _openDialogs = new List<AlertDialog>();

public void CloseAllDialogs()
{
    foreach (var dialog in _openDialogs)
    {
        dialog.Dismiss();
    }
    _openDialogs.Clear();
}


public async Task ShowMessageAsync(string title, string message)
{
    await Task.Run(() => ShowAlert(title, message, "OK", null, null, false, false));
}


public async Task ShowErrorAsync(string title, Exception error, string buttonText, Action<bool> callback, bool cancelableOnTouchOutside = false, bool cancelable = false)
{
    await Task.Run(() => ShowAlert(title, error.ToString(), buttonText, null, callback, cancelableOnTouchOutside, cancelable));
}

public async Task ShowMessageAsync(string title, string message, string buttonText, Action<bool> callback, bool cancelableOnTouchOutside = false, bool cancelable = false)
{
    await Task.Run(() => ShowAlert(title, message, buttonText, null, callback, cancelableOnTouchOutside, cancelable));
}


public async Task ShowMessageAsync(string title, string message, string buttonConfirmText, string buttonCancelText, Action<bool> callback, bool cancelableOnTouchOutside = false, bool cancelable = false)
{
    await Task.Run(() => ShowAlert(title, message, buttonConfirmText, buttonCancelText, callback, cancelableOnTouchOutside, cancelable));
}


I am tunneling the defined Tasks of the interface via a call to Task.Run()  into one single method call that is able to handle all scenarios I want to support. Let’s have a look at the ShowAlert method:

internal void ShowAlert(string title, string content, string confirmButtonText = null, string cancelButtonText = null, Action<bool> callback = null, bool cancelableOnTouchOutside = false, bool cancelable = false)
{
    var alert = new AlertDialog.Builder(Forms.Context);
    alert.SetTitle(title);
    alert.SetMessage(content);

    if (!string.IsNullOrEmpty(confirmButtonText))
    {
        alert.SetPositiveButton(confirmButtonText, (sender, e) =>
        {
            callback?.Invoke(true);
            _openDialogs.Remove((AlertDialog)sender);
        });
    }

    if (!string.IsNullOrEmpty(cancelButtonText))
    {
        alert.SetNegativeButton(cancelButtonText, (sender, e) =>
        {
            callback?.Invoke(false);
            _openDialogs.Remove((AlertDialog)sender);
        });
    }

    Device.BeginInvokeOnMainThread(() =>
    {
        var dialog = alert.Show();
        _openDialogs.Add(dialog);
        dialog.SetCanceledOnTouchOutside(cancelableOnTouchOutside);
        dialog.SetCancelable(cancelable);

        if (cancelableOnTouchOutside || cancelable)
        {
            dialog.CancelEvent += (sender, e) =>
            {
                callback?.Invoke(false);
                _openDialogs.Remove((AlertDialog)sender);
            };
        }


    });
}

In the first three lines I am setting up a new AlertDialog , taking into account the actual Xamarin.Forms.Context, setting the title and the message content. If no other option is used, this shows just with the standard “OK”-Button to close the message.

Often we want to modify the button text, that’s where the confirmButtonText and cancelButtonTextoverloads are being used. I am also using a callback method that takes a Boolean to show which button on the message was pressed. Showing the Dialog needs to be done on the main UI Thread. Xamarin Forms provides the Device.BeginInvokeOnMainThread method to dispatch the code within the action into the right place.

I am showing the dialog while keeping a reference in the _openDialogs List. This reference is removed once the matching button or cancel action is executed. If the message is allowed to be dismissed via outside touches or other cancel methods, this happens in the CancelEvent Eventhandler delegate I am attaching.

The implementation also has a way to close all open dialogs, but it is a good practice to have only one open at a time, especially as other platforms do support only one open dialog at a time.

UWP

Microsoft recommends to use the ContentDialog class to show messages and dialogs of all kind. So this is what we will use to show our dialog messages. Like on Android, we need a Task.Run()wrapper to make the implementation async.

List<ContentDialog> _openDialogs = new List<ContentDialog>(); 
  
  
public void CloseAllDialogs() 
{ 
    foreach (var dialog in _openDialogs) 
    { 
        dialog.Hide(); 
    } 
    _openDialogs.Clear(); 
} 
  
  
public async Task ShowErrorAsync(string title, Exception error, string buttonText, Action<bool> closeAction, bool cancelableOnTouchOutside = false, bool cancelable = false) 
{ 
    await Task.Run(() => { ShowContentDialog(title, error.ToString(), buttonText, null, closeAction, cancelableOnTouchOutside, cancelable); }); 
} 
  
public async Task ShowMessageAsync(string title, string message) 
{ 
    await Task.Run(() => { ShowContentDialog(title, message, "OK", null, null, false, false); }); 
} 
  
public async Task ShowMessageAsync(string title, string message, string buttonText, Action<bool> closeAction, bool cancelableOnTouchOutside = false, bool cancelable = false) 
{ 
    await Task.Run(() => { ShowContentDialog(title, message, buttonText, null, closeAction, cancelableOnTouchOutside, cancelable); }); 
} 
  
public async Task ShowMessageAsync(string title, string message, string buttonConfirmText, string buttonCancelText, Action<bool> closeAction, bool cancelableOnTouchOutside = false, bool cancelable = false) 
{ 
    await Task.Run(() => { ShowContentDialog(title, message, buttonConfirmText, buttonCancelText, closeAction, cancelableOnTouchOutside, cancelable); }); 
} 
  

Even if UWP allows only one ContentDialog to be open, we are using the list of open dialogs to be able to close “them” for compatibility reasons. The next step to implement is the ShowContentDialog Task all methods above are using:

internal void ShowContentDialog(string title, string content, string confirmButtonText = null, string cancelButtonText = null, Action<bool> callback = null, bool cancelableOnTouchOutside = false, bool cancelable = false) 
{ 
    Device.BeginInvokeOnMainThread(async () => 
    { 
        var messageDialog = new ContentDialog() 
        { 
            Title = title, 
            Content = content,                     
        }; 
  
  
    if (!string.IsNullOrEmpty(confirmButtonText)) 
    { 
  
        if (string.IsNullOrEmpty(cancelButtonText)) 
        { 
            messageDialog.CloseButtonText = confirmButtonText; 
  
            messageDialog.CloseButtonClick += (sender, e) => 
            { 
                callback?.Invoke(true); 
                _openDialogs.Remove((ContentDialog)sender); 
            }; 
        } 
        else 
        { 
            messageDialog.PrimaryButtonText = confirmButtonText; 
  
            messageDialog.PrimaryButtonClick += (sender, e) => 
            { 
                callback?.Invoke(true); 
                _openDialogs.Remove((ContentDialog)sender); 
            }; 
  
        } 
    } 
  
        if (!string.IsNullOrEmpty(cancelButtonText)) 
        { 
            messageDialog.CloseButtonText = cancelButtonText; 
  
            messageDialog.CloseButtonClick += (sender, e) => 
            { 
                callback?.Invoke(false); 
                _openDialogs.Remove((ContentDialog)sender); 
            }; 
        } 
  
  
  
        _openDialogs.Add(messageDialog); 
  
        await messageDialog.ShowAsync(); 
    }); 
} 

The setup of the dialog is kind of similar to android. First, we are creating a new dialog setting the title and the message.

The second part is a bit more complex here. Dialogs should hook into the CloseButton properties and events in all cases, at least after OS-Version 1703 (Creators Update). This way, the CloseButtonClickevent is also raised when the user presses the ESC-Button, the system back button, the close button of the dialog as well as the B-Button on the Xbox-Controller.

When we have only one button to show, our confirmButtonText is directed to the CloseButton, otherwise to the PrimaryButton. In the second case, the CloseButtonis connected with the cancelButtonText. We are using the same callback Action as on Android, where the bool parameter indicates which button was pressed.

In the UWP implementation the additional parameters cancelableOnTouchOutsideand cancelableare not used.

iOS

The base implementation on iOS is basically the same like on Android and UWP. In case of iOS, we are using the UIAlertController class, which is mandatory since iOS 8.

List<UIAlertController> _openDialogs = new List<UIAlertController>();

public void CloseAllDialogs()
{
    foreach (var dialog in _openDialogs)
    {
        Device.BeginInvokeOnMainThread(() =>
        {
            dialog.DismissViewController(true, null);
        });
    }
    _openDialogs.Clear();
}

public async Task ShowErrorAsync(string title, Exception error, string buttonText, Action<bool> closeAction, bool cancelableOnTouchOutside = false, bool cancelable = false)
{
    await Task.Run(() => { ShowAlert(title, error.ToString(), buttonText, null, closeAction, cancelableOnTouchOutside, cancelable); });
}

public async Task ShowMessageAsync(string title, string message)
{
    await Task.Run(() => { ShowAlert(title, message, "OK", null, null, false, false); });
}

public async Task ShowMessageAsync(string title, string message, string buttonText, Action<bool> closeAction, bool cancelableOnTouchOutside = false, bool cancelable = false)
{
    await Task.Run(() => { ShowAlert(title, message, buttonText, null, closeAction, cancelableOnTouchOutside, cancelable); });
}

public async Task ShowMessageAsync(string title, string message, string buttonConfirmText, string buttonCancelText, Action<bool> closeAction, bool cancelableOnTouchOutside = false, bool cancelable = false)
{
    await Task.Run(() => { ShowAlert(title, message, buttonConfirmText, buttonCancelText, closeAction, cancelableOnTouchOutside, cancelable); });
}

Now that we have the Task wrappers in place, we need to implement the ShowAlert method:

internal void ShowAlert(string title, string content, string confirmButtonText = null, string cancelButtonText = null, Action<bool> callback = null, bool cancelableOnTouchOutside = false, bool cancelable = false)
{
    //all this code needs to be in here because UIKit demands the main UI Thread
    Device.BeginInvokeOnMainThread(() =>
    {
        var dialogAlert = UIAlertController.Create(title, content, UIAlertControllerStyle.Alert);

        var okAction = UIAlertAction.Create(!string.IsNullOrEmpty(confirmButtonText) ? confirmButtonText : "OK", UIAlertActionStyle.Default, _ =>
        {
            callback?.Invoke(true);
            _openDialogs.Remove(dialogAlert);
        });
        dialogAlert.AddAction(okAction);


        if (!string.IsNullOrEmpty(cancelButtonText))
        {
            var cancelAction = UIAlertAction.Create(cancelButtonText, UIAlertActionStyle.Cancel, _ =>
            {
                callback?.Invoke(false);
                _openDialogs.Remove(dialogAlert);
            });
            dialogAlert.AddAction(cancelAction);
        }
        _openDialogs.Add(dialogAlert);

        var rootController = UIApplication.SharedApplication.KeyWindow.RootViewController;

        rootController.PresentViewController(dialogAlert, true, null);
    });
}

What I am doing here is straight forward – I am setting up a new UIAlertController instance via its creation method, telling it to be styled as an alert. Then I need to create two UIAlertAction instances, one for the confirmButtonText and one for the cancelButtonText.  Of course, I am hooking up the prior defined callback action, which will inform the Xamarin.Forms class about the result of the dialog.

To display the Alert, we need a reference to the RootViewController of the iOS application. In most Xamarin.Forms applications, the above code will do the job to present the UIAlertController via the PresentViewController method provided by the OS. Like the UWP implementation, also the iOS implementation needs to be executed in the main UI thread, because the UIKit demands it. That’s why also here, the whole code is running inside the Device.BeginInvokeOnMainThread method’s action delegate.

The additional parameters cancelableOnTouchOutsideand cancelableare not used on iOS.

Updating our ViewModelLocator

If you have read my post on Dependency Injection, you might remember that we are able to combine the power of MVVMLight with Xamarin.Forms own DependencyService. This is what we will do once again in our ViewModelLocator in the RegisterServices method:

var dialogService = DependencyService.Get<IDialogService>();
SimpleIoc.Default.Register<IDialogService>(() => dialogService);

And that’s already all we need to do here. Really.

Finally: Showing message dialogs

I added three buttons to the sample’s main page. One shows a simple message, one shows the exception that I manually throw and the last one provides a two choice dialog. Let’s have a quick look at the commands bound to them:

 
private RelayCommand _showMessageCommand; 
  
public RelayCommand ShowMessageCommand => _showMessageCommand ?? (_showMessageCommand = new RelayCommand(async () => 
{ 
    await SimpleIoc.Default.GetInstance<IDialogService>().ShowMessageAsync("Cool... ?", "You really clicked this button!"); 
}));

This shows a simple message without using the additional parameters. I use this one primarily for confirmations.

private RelayCommand _showErrorWithExceptionCommand;

public RelayCommand ShowErrorWithExceptionCommand => _showErrorWithExceptionCommand ?? (_showErrorWithExceptionCommand = new RelayCommand(async () =>
{
    try
    {
        throw new NotSupportedException("You tried to fool me, which is not supported!");
    }
    catch (Exception ex)
    {
        await SimpleIoc.Default.GetInstance<IDialogService>().ShowErrorAsync("Error", ex, "Sorry",
            returnValue =>
            {
                Debug.WriteLine($"{nameof(ShowErrorWithExceptionCommand)}'s dialog returns: {returnValue}");
            }, false, false);
    }
}));

This one takes an exception and shows it on the screen. I use them mainly for developing purposes.

private RelayCommand _showSelectionCommand;

public RelayCommand ShowSelectionCommand => _showSelectionCommand ?? (_showSelectionCommand = new RelayCommand(async () =>
{

    await SimpleIoc.Default.GetInstance<IDialogService>().ShowMessageAsync("Question:",
        "Do you enjoy this blog series about MVVMLight and Xamarin Forms?", "yeah!", "nope", async returnvalue =>
        {
            if (returnvalue)
            {
                await SimpleIoc.Default.GetInstance<IDialogService>()
                    .ShowMessageAsync("Awesome!", "I am glad you like it");
            }
            else
            {
                await SimpleIoc.Default.GetInstance<IDialogService>()
                    .ShowMessageAsync("Oh no...", "Maybe you could send me some feedback on how to improve it?");
            }
        },
        false, false);

}));

This one provides a choice between two options. A good example where I use this is when there is no internet connection and I ask the user to open the WiFi settings or cancel. In the sample, I am also showing another simple message after one of the buttons has been pressed. The content of this simple message depends on which button was clicked.

Action, please!

This slideshow requires JavaScript.

 

Using Xamarin.Forms’ DependencyServicetogether with the SimpleIoc implementation of MVVMLight, we are once again easily able to connect platform specific code to our Xamarin.Forms project. Every platform implementation follows the dialog recommendations and is executed using the native implementations while keeping some options open to use different kind of message dialogs.

As always, I hope this post is helpful for some of you. Until the next post, happy coding!

Posted by msicc in Android, Dev Stories, iOS, Windows, Xamarin, 1 comment
[Updated] Xamarin Forms, the MVVMLight Toolkit and I: navigation and modal pages

[Updated] Xamarin Forms, the MVVMLight Toolkit and I: navigation and modal pages

After showing you the basic MVVMLight Setup I am using as well as how to combine Xamarin.Forms’ DependencyService with our own Dependecy Injection-mechanism, this article is all about Navigation and modal pages in Xamarin.Forms.

Some preliminary words

I always liked how the MVVMLight Toolkit provided the NavigationService for my Windows & Windows Phone applications. That said, I tried to keep the idea of its NavigationService and ported it over to my Xamarin.Forms structure. I also extended it to fit the needs of my XF apps, for example for pushing modal pages (we’ll see that later). So for the base idea, I have to say thanks to Laurent Bugnion for the Windows platform implementation in MVVMLight and for keeping it simple. The later fact allows one to easily extend and adapt the service.

Also, there are tons of really good and also working samples around the web to show navigation in Xamarin.Forms. However, most of them follow another strategy, so I came to the point where decided to write my own implementation. My way may work for most scenarios without making a difference between navigation and showing modal pages. It provides an easy implementation and usage while following the MVVM pattern as far as it can go with Xamarin.Forms.

Components

My implementation has some key components, which I will describe briefly in this post:

  • Interfaces for Navigation and view events
  • Implementation of these interfaces
  • using the implementations in views
  • using the implementations in ViewModels

Interfaces for the win!

If we want to follow the MVVM pattern, we need to keep our Views completely separated from our ViewModels. A common practice to achieve this goal is the usage of interfaces, and so do I. If you have read my previous blog post about Dependency Injection, you know already a bit about the things we have to do. First, we will create an interface for the navigation itself:

public interface IXfNavigationService
{
    void Initialize(NavigationPage navigation);
    void Configure(string pageKey, Type pageType);
    (bool isRegistered, bool isModal) StackContainsNavKey(string pageKey);
    Task GoHomeAsync();
    Task GoBackAsync();
    Task GoBackModalAsync();
    int ModalStackCount { get; }
    string CurrentModalPageKey { get; }
    Task ShowModalPageAsync(string pageKey, bool animated = true);
    Task ShowModalPageAsync(string pageKey, object parameter, bool animated = true);
    int NavigationStackCount { get; }
    string CurrentPageKey { get; }
    Task NavigateToAsync(string pageKey, bool animated = true);
    Task NavigateToAsync(string pageKey, object parameter, bool animated = true);
}

As you can see, it is a pretty big interface that covers nearly all possible navigation scenarios of a Xamarin.Forms app (at least those that I had to deal with already). We are going to hook into a Xamarin.Forms  NavigationPage and configure our page handling cache with the configure method. As all navigation methods in Xamarin Forms are async, all navigational tasks will be implemented async as well. Additionally, we will have some helpful properties that we can use in our application implementation.

In Windows applications, we have some additional events for pages like  Loaded or OnNavigatedTo(and so on). Xamarin.Forms pages have something similar: ViewAppearing and ViewDisappearing. These two events correspond to OnNavigatedTo and OnNavigatedFrom in a Windows application. Sometimes, we need to know when those events happen in our ViewModels or other places behind the scenes to get stuff done. That’s why I created an interface for this purpose:

public interface IViewEventBrokerService
{
    event EventHandler<ViewEventBrokerEventArgs> ViewAppearing;
    event EventHandler<ViewEventBrokerEventArgs> ViewDisAppearing;
    void RaiseViewAppearing(string pageKey, Type pageType, bool isModal);
    void RaiseViewDisAppearing(string pageKey, Type pageType, bool isModal);
}

I also created my own EventArgs to make it easier to pass all data around (as you can see above). Here is the class:

public class ViewEventBrokerEventArgs : EventArgs
{
    public ViewEventBrokerEventArgs(string pageKey, Type pageType, bool isModal)
    {
        PageKey = pageKey;
        PageType = pageType;
        IsModal = isModal;
    }
    public string PageKey { get; private set; }
    public Type PageType { get; private set; }
    public bool IsModal { get; private set; }
}

Now that we have our interfaces defined, we are going the next step and have a look into their implementations.

IXfNavigationService implementation

First it is important to understand what Xamarin.Forms does when we are using a NavigationPage. We are performing a hierarchical navigation here. A must read is this page from the Xamarin documentation.

So you’re back from reading the documentation? Great, then lets have a look what our XfNavigationServiceimplementation does. It builds on top of the Xamarin.Forms NavigationPage, which implements the INavigation interface. Other solutions I saw are pulling down this interface and implement it in their implementation. I prefer to keep it simple and just use the already implemented interface in the Xamarin.Forms NavigationPage, which is mandatory for my implementation. We are pulling it into our implementation with the Initialize(NavigationPage navigationPage) method:

public void Initialize(NavigationPage navigationPage)
{
    _navigationPage = navigationPage;
}

We could also use a constructor injection here. Most of the time it would work, but I had some problems to get the timing right under certain circumstances. That’s why I prefer to manually initialize it to overcome these timing problems  – and it does not really hurt in real life applications to have it a bit more under control.

Before we are going to see the actual implementation, I need to break out of this scope and explain a threading issue.

Locking the current executing thread

Often we are running a lot of code at the same time. This could bring up some issues with ourXfNavigationService. If multiple threads try to change or execute code from our interface implementation, the result may not the one we desired. To prevent this, we would normally use the lock statement to allow only one thread modifying our code. Problem with the lock statement is, that we cannot run asynchronous code within.

As asynchronous code execution removes some of the headache in programming, we need a solution for this. And there is one, utilizing the SemaphoreSlim class of the .NET framework. Basically, the SemaphoreSlim class provides a single application Semaphore implementation. Without going deeper into it, we are replacing the lock statement we would normally use with this. We just need to initialize the SemaphoreSlim class as a private static member:

//using this instead of lock statement
private static SemaphoreSlim _lock = new SemaphoreSlim(1, 1);

This will only allow one thread to access the objects we are passing after it, and before releasing it (which is our responsibility). The code itself is recommended to run in a try..finally  block (you’ll see that below). Pretty much the same thing the lock statement would do, but with the possibility to run asynchronous code.

Back to the implementation

The next step is to allow registering pages with a name and their type from the ViewModelLocator. I am doing the same as in the standard MVVMLight implementation here:

//declare private member for the registered pages cache
private readonly Dictionary<string, Type> _pagesByKey = new Dictionary<string, Type>();


public void Configure(string pageKey, Type pageType) 
{ 
    //synchronous lock 
    _lock.Wait(); 
    try 
    { 
        if (_pagesByKey.ContainsKey(pageKey)) 
        { 
            _pagesByKey[pageKey] = pageType; 
        } 
        else 
        { 
            _pagesByKey.Add(pageKey, pageType); 
        } 
    } 
    finally 
    { 
        _lock.Release(); 
    } 
} 

Once we have our pages configured (we’ll see that later in this post), we are easily able to identify our registered pages for navigation purposes. Sometimes we want to get the current Page, so we need to implement a property for that, as well as for the current page key and the current modal page key:

public Page GetCurrentPage()
{
    return _navigationPage?.CurrentPage;
}


public string CurrentPageKey 
{ 
    get 
    { 
        _lock.Wait(); 
        try 
        { 
            if (_navigationPage?.CurrentPage == null) 
            { 
                return null; 
            } 
  
            var pageType = _navigationPage.CurrentPage.GetType(); 
  
            return _pagesByKey.ContainsValue(pageType) 
                ? _pagesByKey.First(p => p.Value == pageType).Key 
                : null; 
        } 
        finally 
        { 
            _lock.Release(); 
        } 
    } 
} 


public string CurrentModalPageKey 
{ 
    get 
    { 
        _lock.Wait(); 
  
        try 
        { 
            if (ModalStackCount == 1) 
            { 
                return null; 
            } 
  
            //only INavigation holds the ModalStack 
            var pageType = _navigationPage.Navigation.ModalStack.Last().GetType(); 
  
            return _pagesByKey.ContainsValue(pageType) ? _pagesByKey.FirstOrDefault(p => p.Value == pageType).Key 
                : null; 
        } 
        finally 
        { 
            _lock.Release(); 
        } 
    } 
} 

I found myself in situations where I needed to check if I am on a modal page, so lets add a method for that:

public (bool isRegistered, bool isModal) StackContainsNavKey(string pageKey) 
{ 
  
    bool isUsedModal = false; 
    bool isRegistered = false; 
  
    _lock.Wait(); 
    try 
    { 
        isRegistered = _pagesByKey.ContainsKey(pageKey); 
  
  
        if (isRegistered) 
        { 
            var pageType = _pagesByKey.SingleOrDefault(p => p.Key == pageKey).Value; 
  
            var foundInNavStack = _navigationPage.Navigation.NavigationStack.Any(p => p.GetType() == pageType); 
            var foundInModalStack = _navigationPage.Navigation.ModalStack.Any(p => p.GetType() == pageType); 
  
            if (foundInNavStack && !foundInModalStack || !foundInNavStack && !foundInModalStack) 
            { 
                isUsedModal = false; 
            } 
            else if (foundInModalStack && !foundInNavStack) 
            { 
                isUsedModal = true; 
            } 
            else 
            { 
                throw new NotSupportedException("Pages should be used exclusively Modal or for Navigation"); 
            } 
        } 
        else 
        { 
            throw new ArgumentException($"No page with key: {pageKey}. Did you forget to call the Configure method?", nameof(pageKey)); 
        } 
    } 
    finally 
    { 
        _lock.Release(); 
    } 
  
    return (isRegistered, isUsedModal); 
} 

This method checks if a page is registered correctly with its key and if it is presented modal at the moment. It also makes sure that an exception is thrown if a page is used modal AND in a navigation flow, which I think is a good practice to avoid problems when using the service. Finally, let’s add a Task for navigation to another page:

public async Task NavigateToAsync(string pageKey, object parameter, bool animated = true) 
{ 
    await _lock.WaitAsync(); 
  
    try 
    { 
  
        if (_pagesByKey.ContainsKey(pageKey)) 
        { 
            var type = _pagesByKey[pageKey]; 
            ConstructorInfo constructor = null; 
            object[] parameters = null; 
  
            if (parameter == null) 
            { 
                constructor = type.GetTypeInfo() 
                    .DeclaredConstructors 
                    .FirstOrDefault(c => !c.GetParameters().Any()); 
  
                parameters = new object[] 
                { 
                }; 
            } 
            else 
            { 
                constructor = type.GetTypeInfo() 
                    .DeclaredConstructors 
                    .FirstOrDefault( 
                        c => 
                        { 
                            return c.GetParameters().Count() == 1 
                                   && c.GetParameters()[0].ParameterType == parameter.GetType(); 
                        }); 
  
                parameters = new[] { parameter }; 
            } 
  
            if (constructor == null) 
            { 
                throw new InvalidOperationException("No constructor found for page " + pageKey); 
            } 
  
            var page = constructor.Invoke(parameters) as Page; 
            if (_navigationPage != null) 
            { 
                Device.BeginInvokeOnMainThread(async () => 
                { 
                    await _navigationPage.Navigation.PushAsync(page, animated); 
                }); 
            } 
            else 
            { 
                throw new NullReferenceException("there is no navigation page present, please check your page architecture and make sure you have called the Initialize Method before."); 
            } 
        } 
        else 
        { 
            throw new ArgumentException( 
                $"No page with key: {pageKey}. Did you forget to call the Configure method?", 
                nameof(pageKey)); 
        } 
    } 
    finally 
    { 
        _lock.Release(); 
    } 
} 

[Update:] Until the latest Xamarin.Forms release, there was no need to use the Device.BeginInvokeOnMainThreadmethod for the navigation itself. I only checked it recently that the Navigation needs now the call to it to dispatch the navigation to the main UI thread. Otherwise, the navigation will end in a dead thread on Android and iOS (but strangely not for UWP). I updated the code above and the source on Github as well.

I try to avoid passing parameters to pages while navigating, that’s why I added another task without the parameter overload as well:

public async Task NavigateToAsync(string pageKey, bool animated = true)
{
    await NavigateToAsync(pageKey, null, animated);
}

Of course we will run into situations where we want to go back manually, for example in a cancel function. So we have a method for that as well:

public async Task GoBackAsync()
{
    await _navigationPage.Navigation.PopAsync(true);
}

That’s  a lot of functionality already, but until now, we are only able to navigate to other pages and back. We want to support modal pages as well, so we’ll have some more methods to implement. They are following the same syntax as their navigation counterpart, so no surprise here:

public async Task ShowModalPageAsync(string pageKey, object parameter, bool animated = true) 
{ 
    await _lock.WaitAsync(); 
  
    try 
    { 
  
        if (_pagesByKey.ContainsKey(pageKey)) 
        { 
            var type = _pagesByKey[pageKey]; 
            ConstructorInfo constructor = null; 
            object[] parameters = null; 
  
            if (parameter == null) 
            { 
                constructor = type.GetTypeInfo() 
                    .DeclaredConstructors 
                    .FirstOrDefault(c => !c.GetParameters().Any()); 
  
                parameters = new object[] 
                { 
                }; 
            } 
            else 
            { 
                constructor = type.GetTypeInfo() 
                    .DeclaredConstructors 
                    .FirstOrDefault( 
                        c => 
                        { 
                            return c.GetParameters().Count() == 1 
                                   && c.GetParameters()[0].ParameterType == parameter.GetType(); 
                        }); 
  
                parameters = new[] { parameter }; 
            } 
  
  
            var page = constructor.Invoke(parameters) as Page; 
  
            if (_navigationPage != null) 
            { 
                Device.BeginInvokeOnMainThread(async () => 
                { 
                    await _navigationPage.Navigation.PushModalAsync(page, animated); 
                }); 
            } 
            else 
            { 
                throw new NullReferenceException("there is no navigation page present, please check your page architecture and make sure you have called the Initialize Method before."); 
            } 
        } 
        else 
        { 
            throw new ArgumentException($"No page found with key: {pageKey}. Did you forget to call the Configure method?", nameof(pageKey)); 
        } 
    } 
    finally 
    { 
        _lock.Release(); 
    } 
} 

public async Task GoBackModalAsync()
{
    await _navigationPage.Navigation.PopModalAsync(true);
}

The last things that I wanted to note are properties that return the current counts of both the modal and the navigation stack of the navigation page as well as the GoHomeAsync() method to return to the root page. You will see these in the source code on Github.

IViewEventBrokerService implementation

Like I wrote already before, sometimes we need to know when a view is appearing/disappearing. In that case, the IViewEventBrokerService comes in. The implementation is pretty straight forward:

public class ViewEventBrokerService : IViewEventBrokerService
{
    public event EventHandler<ViewEventBrokerEventArgs> ViewAppearing;
    public event EventHandler<ViewEventBrokerEventArgs> ViewDisAppearing;


    public void RaiseViewAppearing(string pageKey, Type pageType, bool isModal)
    {
        ViewAppearing?.Invoke(this, new ViewEventBrokerEventArgs(pageKey, pageType, isModal));
    }

    public void RaiseViewDisAppearing(string pageKey, Type pageType, bool isModal)
    {
        ViewDisAppearing?.Invoke(this, new ViewEventBrokerEventArgs(pageKey, pageType, isModal));
    }
}

We have two events that can be raised with their corresponding Raise… methods. That’s all we have to do in here.

Implementing the Interfaces in Views (Pages)

Well, we have written a lot of code until here, now it is time to actually use it. As I want all my pages to be raise their appearing and disappearing automatically, I created a new base class, derived from Xamarin.Forms’ ContentPage:

public class XfNavContentPage : ContentPage
{
    private IViewEventBrokerService _viewEventBroker;
    private IXfNavigationService _navService;

    public XfNavContentPage()
    {
        _viewEventBroker = SimpleIoc.Default.GetInstance<IViewEventBrokerService>();
        _navService = SimpleIoc.Default.GetInstance<IXfNavigationService>();
    }

    public static BindableProperty RegisteredPageKeyProperty = BindableProperty.Create("RegisteredPageKey", typeof(string), typeof(XfNavContentPage), default(string), BindingMode.Default, propertyChanged: OnRegisteredPageKeyChanged);

    private static void OnRegisteredPageKeyChanged(BindableObject bindable, object oldValue, object newValue)
    {
        //todo, but not needed atm.
    }

    public string RegisteredPageKey
    {
        get { return (string)GetValue(RegisteredPageKeyProperty); }
        set { SetValue(RegisteredPageKeyProperty, value); }
    }

    private(bool isRegistered, bool isModal) _stackState { get; private set; }

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

        if (!string.IsNullOrEmpty(RegisteredPageKey))
        {
            _stackState = _navService.StackContainsNavKey(RegisteredPageKey);

            if (_stackState.isRegistered)
            {
                _viewEventBroker?.RaiseViewAppearing(RegisteredPageKey, GetType(), _stackState.isModal);
            }
        }
    }

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

        if (!string.IsNullOrEmpty(RegisteredPageKey))
        {
            if (_stackState.isRegistered)
            {
                _viewEventBroker?.RaiseViewDisAppearing(RegisteredPageKey, GetType(), _stackState.isModal);
            }
        }
    }
}

Let me explain what this base class does. It provides a BindableProperty(which is the Xamarin.Forms version of a DependencyProperty) that takes the registered key to provide it as a parameter. You can bind the key from your ViewModel or set it in code behind/XAML directly, all these ways will work. The base page implements our interfaces of the IXfNavigationService and the IViewBrokerServiceinterfaces as members and loads them in its constructor. The _stackStatemember is just an easy way to provide the needed data to the event-raising methods of our IViewEventBrokerservice. If used correctly, every page that derives from this base class will throw the corresponding events, which can be used in other parts of our application then.

Implementing the Interfaces in ViewModels

Like I did for Views, I am also creating a new base class for ViewModels that implement our two interfaces. Here is how it looks like:

public class XfNavViewModelBase : ViewModelBase
{
    protected readonly IXfNavigationService _navService;

    protected readonly IViewEventBrokerService _viewEventBroker;


    public XfNavViewModelBase()
    {
        _navService = SimpleIoc.Default.GetInstance<IXfNavigationService>();
        _viewEventBroker = SimpleIoc.Default.GetInstance<IViewEventBrokerService>();
        _viewEventBroker.ViewAppearing += OnCorrespondingViewAppearing;
        _viewEventBroker.ViewDisAppearing += OnCorrespondingViewDisappearing;
    }


    protected virtual void OnCorrespondingViewAppearing(object sender, ViewEventBrokerEventArgs e)
    {
    }

    protected virtual void OnCorrespondingViewDisappearing(object sender, ViewEventBrokerEventArgs e)
    {
    }

    private string _correspondingViewKey;

    public string CorrespondingViewKey
    {
        get => _correspondingViewKey; set => Set(ref _correspondingViewKey, value);
    }

    public bool IsBoundToModalView()
    {
        if (!string.IsNullOrEmpty(CorrespondingViewKey))
        {
            var checkIfIsModal = _navService.StackContainsNavKey(CorrespondingViewKey);

            if (checkIfIsModal.isRegistered)
            {
                return checkIfIsModal.isModal;
            }
        }
        return false;
    }
}

The XfNavViewModelBase implements both the IXfNavigationService and the IViewEventBrokerService interfaces. It also registers for the events thrown by IViewEventBrokerService. Making them virtual allows us to override them in derived ViewModels, if we need to. It has a string property to set the name of the View we want to use it in as well as a method that checks automatically if we are on a modal page if it gets called.

Using the created navigation setup

Now our navigation setup is ready it is time to have a look into how to use it. First we are going to create two pages, one for being shown modal, and one for being navigated to.

created-pages-snip

Then we’ll need to register and configure our services and pages in the ViewModelLocator. Remember the static RegisterServices() method we created in the first post? This is were we will throw the interface registrations in:

private static void RegisterServices() 
{ 
    //this one gets the correct service implementation from platform implementation 
    var osService = DependencyService.Get<IOsVersionService>(); 
  
    // which can be used to register the service class with MVVMLight's Ioc 
    SimpleIoc.Default.Register<IOsVersionService>(() => osService); 
  
    SimpleIoc.Default.Register<IXfNavigationService>(GetPageInstances); 
    SimpleIoc.Default.Register<IViewEventBrokerService, ViewEventBrokerService>(); 
}

The method contains already our IOsVersionService from my last blog post. We are also using DI here for the IXfNavigationService, as we need to Configure our page keys as well. First, we are adding static strings as page keys to the ViewModelLocator:

public static string ModalPageKey => nameof(ModalPage);
public static string NavigatedPageKey => nameof(NavigatedPage);

I am always using the nameof()-operator for this, because it makes life a bit easier. The second step is the missing piece in the service registration, the GetPageInstances() method that returns an instance of the IXfNavigationService interface implentation and registers our two pages via the Configure() method.

public static XfNavigationService GetPageInstances()
{
    var nav = new XfNavigationService();

    nav.Configure(ModalPageKey, typeof(ModalPage));
    nav.Configure(NavigatedPageKey, typeof(NavigatedPage));

    return nav;
}

This all will never work if we are not using a NavigationPage. So we are going to load MainPage.xaml as a NavigationPagein App.xaml.cs and pass the navigation page to our IXfNavigationService:

public App()
{
    InitializeComponent();

    var rootNavigation = new NavigationPage(new View.MainPage());
    MainPage = rootNavigation;
    SimpleIoc.Default.GetInstance<IXfNavigationService>().Initialize(rootNavigation);
}

Modifying pages

Until now, the pages we created are standard ContentPages, so we need to make them derive from our earlier created base class. First we are adding the namespace of our base class to it:

xmlns:baseCtrl="clr-namespace:XfMvvmLight.BaseControls;assembly=XfMvvmLight"

After that, we are able to use the base class to change ContentPage to baseCtrl:XfNavContentPage. Now open the code behind file for the page and change it to derive from XfNavContentPage as well:

public partial class ModalPage : XfNavContentPage

The sample project has a modal page and a navigated page to demonstrate both ways.

Setting up ViewModels

Normally, we also have a ViewModel for every additional page. That´s why I created a ModalPageViewModel as well as a NavigatedPageViewModel for the sample. They derive from the XfNavViewModelBase, so wie can easyily hook up the view events (if needed):

public class ModalPageViewModel : XfNavViewModelBase
{ 
    public ModalPageViewModel()
    {
        CorrespondingViewKey = ViewModelLocator.ModalPageKey;
    }
 
    protected override void OnCorrespondingViewAppearing(object sender, ViewEventBrokerEventArgs e)
    {
        base.OnCorrespondingViewAppearing(sender, e);
    }
 
    protected override void OnCorrespondingViewDisappearing(object sender, ViewEventBrokerEventArgs e)
    {
        base.OnCorrespondingViewDisappearing(sender, e);
    }
 
 
    private RelayCommand _goBackCommand;
 
    public RelayCommand GoBackCommand => _goBackCommand ?? (_goBackCommand = new RelayCommand(async () =>
    {
        await _navService.GoBackModalAsync();
    })); 
}

Remember the page keys we added earlier to the ViewModelLocator? We are just setting it as CorrespondingViewKey in the constructor here, but you could choose to it the way you prefer as well and can easily be bound to the view now:

<baseCtrl:XfNavContentPage 
   xmlns="http://xamarin.com/schemas/2014/forms"
   xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
   xmlns:baseCtrl="clr-namespace:XfMvvmLight.BaseControls;assembly=XfMvvmLight"
   x:Class="XfMvvmLight.View.ModalPage" 
   RegisteredPageKey="{Binding CorrespondingViewKey}">
<!--code omitted for readability-->
</baseCtrl:XfNavContentPage>

As the sample pages have a button with back function, we have also a GoBackCommand bound to it. Now that’s already all we need to, and if we set a breakpoint in the event handling overrides, it will be hit as soon as the view is about to appear. See the sample working here in action on Android:

navigation-service-xf-mvvmlight

No we have a fully working and MVVM compliant navigation solution in Xamarin.Forms using the MVVMLight Toolkit.  I know there are several other toolkits and helpers floating around, but I like it to have less dependencies.  Another advantage of going this route: I am mostly familiar with the setup as I am already used to it from my Windows and Windows Phone applications. Creating this setup for navigation does not take a whole lot of time (the initial setup took me around 3 hours including conception). One can also pack the interfaces and the implementations in a (portable) class library to have all this work only once.

If you have feedback for me, feel free to leave a comment below. Like always, I hope this article is helpful for some of you. The updated sample application can be found here on my Github account.

Happy coding, everyone!

 

Posted by msicc in Android, Dev Stories, iOS, Windows, Xamarin, 4 comments
Xamarin Forms, the MVVMLight Toolkit and I: Dependecy Injection

Xamarin Forms, the MVVMLight Toolkit and I: Dependecy Injection

Recap

Let’s just do a small recap what Dependency Injection means. The DI pattern’s main goal is to decouple objects and their dependencies. To separate concerns, we are using this structure nearly every time:

  • interface which defines the provided functionality
  • service class which provides the functionality defined in the interface
  • container that allows client classes/objects to use the functionality defined in the interface

The interface, our helpful dictator

DI always involves an interface, which dictates the functionality of the implementation. In Xamarin Forms, the interface rests inside the PCL/common project:

public interface IOsVersionService
{
    string GetOsVersion { get; } 
}

This interface gets the current installed version of the operating system. The next step ist to create the platform implementation, which is commonly defined as a service class.

Platform Implementation (service class)

We need to implement the service class for each platform. The setup is pretty easy, just add a new class and implement the interface for each platform:

implement-interface-vs2017

Tip: I am using a separate folder for platform implementations and set it to be a namespace provider. This makes it easier to maintain and I keep the same structure in all platform projects.

Let’s have a look into the specific implementations:

Android

public string GetOsVersion
{
    get
    {
        var versionNb = Build.VERSION.Release;
        var codename = Build.VERSION.Codename;
 
        return $"Android {versionNb} ({codename})";
    }
}

iOS

public string GetOsVersion
{
    get
    {
        try
        {
            return $"iOS {UIDevice.CurrentDevice.SystemVersion} ({UIDevice.CurrentDevice.UserInterfaceIdiom})";
 
        }
        catch
        {
            return "This demo supports iOS only for the moment";
        }
    }
}

Windows

public string GetOsVersion
{
    get
    {
        var currentOS = AnalyticsInfo.VersionInfo.DeviceFamily;
 
        var v = ulong.Parse(AnalyticsInfo.VersionInfo.DeviceFamilyVersion);
        var v1 = (v & 0xFFFF000000000000L) >> 48;
        var v2 = (v & 0x0000FFFF00000000L) >> 32;
        var v3 = (v & 0x00000000FFFF0000L) >> 16;
        var v4 = v & 0x000000000000FFFFL;
        var versionNb = $"{v1}.{v2}.{v3}.{v4}";
 
        return $"{currentOS} {versionNb} ({AnalyticsInfo.DeviceForm})";
    }
}

Now that we are able to fetch the OS Version, we need to make the implemation visible outside of the platform assemblies. On Android and iOS, this one is pretty straigt forward by adding this Attribute on top of the class:

[assembly: Xamarin.Forms.Dependency(typeof(OsVersionService))]

Because Universal Windows projects compile differently, we need to go a different route on Windows. To make the implementation visible, we need to explicit declare the class as an assembly to remain included first (otherwise the .NET Toolchain is likely to strip it away):

protected override void OnLaunched(LaunchActivatedEventArgs e)
{
    //other code for initialization, removed for readabilty
 
    //modified for .NET Compile
    List<Assembly> assembliesToInclude = new List<Assembly>();
    assembliesToInclude.Add(typeof(OsVersionService).GetTypeInfo().Assembly);

    Xamarin.Forms.Forms.Init(e, assembliesToInclude); 
}

Now that we have our platform implementations in place, we can go ahead and use the interface to get the OS versions.

Xamarin Forms DependencyService

With the static DependencyService class, Xamarin Forms provides a static container that is able to resolve interfaces to their native platform implementations. Using it is, once again, pretty straight forward:

private string _osVersionViaDs;
public string OsVersionViaDs
{
    get { return _osVersionViaDs; }
    set { Set(ref _osVersionViaDs, value); }
}
 
private RelayCommand _getOSVersionViaDsCommand;
 
public RelayCommand GetOsVersionViaDsCommand => _getOSVersionViaDsCommand ?? (_getOSVersionViaDsCommand = new RelayCommand(() =>
{
    OsVersionViaDs = DependencyService.Get().GetOsVersion; 
}));

In my sample application, I am using a button that fetches the OS version via Xamarin Forms DependencyService and display it into a label in my view.

Special case UWP, once again

To make this acutally work in an UWP application, we need to register the Service manually. Xamarin recommends to do so in the OnLaunched event, after Xamarin Forms is initialized:

//in OnLaunched event (App.xaml.cs)
//manually register for DependencyService 
//AFTER Forms is initialized but BEFORE VMLocator is initialized:
Xamarin.Forms.DependencyService.Register<OsVersionService>();

Only with that extra line of code, it will actually work like it should. If you want to know more on the fact that UWP needs a separate solution, take a look here into the Xamarin docs.

Why use the MVVMLight Toolkit’s Ioc?

There are several reasons. First is of course, purely personal: because I am used to write code for it. But there are also technical reasons:

  • support for cunstroctor injection
  • interface implementations can have parametered constructors
  • MVVMLight supports additional features like named instances and immediate creation on registration
  • in MVVM(Light) applications, you are very likely using DI on Xamarin Forms level, anyway (like in a NavigationService)

You see, there are some (in my opinion) good reasons to use the built in Ioc of the MVVMLight Toolkit.

How to use SimpleIoc and DependencyService together

If you are not relying on the DI-System of Xamarin Forms, you will have to write a lot of code yourself to get the platform implementations. That is not necessary, though. As our ViewModelLocator normally is already part of the Xamarin Forms PCL project, it has access  to the DependencyService and can be used to get the right implementation:

//this one gets the correct service implementation from platform implementation
var osService = DependencyService.Get();
 
// which can be used to register the service class with MVVMLight's Ioc
SimpleIoc.Default.Register<IOsVersionService>(() => osService);

This works pretty well for most implementations and provides us the possibility to use all the features MVVMLight provides. The usage then matches to what we are already familiar with:

private string _osVersionViaSimpleIoc;
public string OsVersionViaSimpleIoc
{
    get { return _osVersionViaSimpleIoc; }
    set { Set(ref _osVersionViaSimpleIoc, value); }
} 
 
private RelayCommand _getOSVersionViaSimpleIocCommand;
 
public RelayCommand GetOsVersionViaSimpleIocCommand => _getOSVersionViaSimpleIocCommand ?? (_getOSVersionViaSimpleIocCommand = new RelayCommand(() =>
{
    OsVersionViaSimpleIoc = SimpleIoc.Default.GetInstance().GetOsVersion; 
}));

If you do not want (or it is not possible due to complexity) register the platform implementation directly in the ViewModelLocator, you  can go down another route. You could create a new interface in the Xamarin Forms PCL which references the interface with the platform implentation as a member. Your implementation of this new interface (in Xamarin Forms) will be responsible for the getting the instance of the platform implementation via the built in DepenencyService.

I already used both ways in my recent Xamarin projects, but I prefer the first way that I described above.

Conclusion

Due to the fact that we know the DI pattern already as we (of course) follow the MVVM pattern in our applications, there is no big mystery about using the built in DependencyService of Xamarin Forms. We can easily integrate it into the MVVMLight Toolkit and combine the best of both worlds this way.

Nonetheless, I know that also some beginners are following my posts, so I tried to describe everything a bit more extended. As always, I hope this post is helpful for some of you. In my next post, I will show you how I solved the Navigation “problem” in my Xamarin Forms applications. In the meantime, you can already have a look at the sample code on Github.

Happy coding, everyone!

Posted by msicc in Android, Dev Stories, iOS, Windows, Xamarin, 6 comments

Xamarin Forms, the MVVMLight Toolkit and I (new series) [Updated]

Updated some code parts that needed to be changed in the ViewModelLocator.

Please see also this post for upgrading the project to .netStandard:

Xamarin Forms, the MVVMLight Toolkit and I: migrating the Forms project and MVVMLight to .NET Standard



Like some of you may have already registered, I have been doing the next step and went cross platform with my personal projects. I am primarily using Xamarin Forms, because I eventually like XAML a little too much. I took a break from round about 2 years on my Xamarin usage, and I am happy to see that it has improved a lot in the meantime. While Xamarin Forms still has room for improvementes, one can do already real and serious projects with it. As I like the lightweight MVVMLight toolkit as much as I like XAML, it was a no-brainer for me to start also my recent Xamarin projects with it.

There is quite some setup stuff to do if you want get everything working from the Xamarin Forms PCL, and this post will be the first in a series to explain the way I am currently using. Some of the things I do may be against good practice for Xamarin Forms, but sometimes one has to break out of them to write code more efficiently and also maintain it easier.

Installing MVVM Light into a Xamarin Forms PCL project

Of course, we will start with a new Xamarin Forms project. After selecting the type Cross Platform App in the New Project Dialog in Visual Studio, you’ll be presented with this screen, which was introduced in the Cycle 9 Release of Xamarin:

Select Xamarin Forms as UI Technology and PCL as Code Sharing Strategy to start the solution creation. As it creates several projects, this may take some time, so you may be able to refill your coffee cup in the meantime. Once the project is created, you’ll see 4 projects:

Before we are going to write some code, we will update and add the additional packages from within the NuGet Package Manager. If your are not targeting the Android versions 7.x , Xamarin Forms is not able to use the latest Android Support libraries, so you’ll have to stick with version 23.3.0 of them (see release notes of Xamarin Forms). Since it makes sense for a new app to target the newest Android version, we’ll be updating the Android Support packages for our sample app as well.

If the NuGet Package manager demands you to restart, you’ll better follow its advise. To verify everything is ok with the updated NuGet packages, set the Android project as Startup project and let Visual Studio compile it.

If all goes well, let’s make sure we are using the right UWP compiler version for Visual Studio 2015. The .NETCORE package for the UWP needs to be of Version 5.2.x, as 5.3 is only compatible with Visual Studio 2017.

Once the packages are up to date, we’ll finally download and install MVVMLight. As we will host all of our ViewModel Logic in Xamarin Forms, together with their Views, we just need to install it into the Portable library and into the UWP project:

There will be no changes to the project except adding the reference. We need to set up the structure ourselves. First, create two new folders, View and ViewModel:

Move the MainPage into the View Folder and adjust the Namespace accordingly. The next step is to setup a ViewModelLocator class, which takes a central part of our MVVM structure. Here is what you need for the base structure:

    public class ViewModelLocator
    {
        private static ViewModelLocator _instance;
        public static ViewModelLocator Instance => _instance ?? (_instance = new ViewModelLocator());

        public void Initialize()
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
            RegisterServices();        

        }

        private static void RegisterServices()
        {
            //topic of another blog post
        }

        #region ViewModels  
        #endregion

        #region PageKeys
        #endregion
    }

You may notice some things. First, I am using the singleton pattern for the ViewModelLocator to make sure I have just one instance. I had some problems with multiple instances on Android, and using a singleton class helped to fix them. The second part of the fix is to move everything that is normally in the constructor into the Initialize() method. Now let’s go ahead, add a MainViewModel to the project and to the ViewModelLocator:

        public void Initialize()
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
            RegisterServices();
            if (!SimpleIoc.Default.IsRegistered)
                SimpleIoc.Default.Register<MainViewModel>();
        }

        #region ViewModels
        public MainViewModel MainVm => ServiceLocator.Current.GetInstance<MainViewModel>();
        #endregion

Let’s give the MainViewModel just one property which is not subject to change (at least for now):

public string HelloWorldString { get; private set; } = "Hello from Xamarin Forms with MVVM Light";

The next step is to get the App.xaml file code right, it should look like this:

<?xml version="1.0" encoding="utf-8"?>
<Application xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             x:Class="XfMvvmLight.App" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             d1p1:Ignorable="d" 
             xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:forms="http://xamarin.com/schemas/2014/forms" 
             xmlns:vm="clr-namespace:XfMvvmLight.ViewModel" >
  <Application.Resources>
    <!-- Application resource dictionary -->
    <forms:ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
      <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
    </forms:ResourceDictionary>
  </Application.Resources>
</Application>

Now that we have set up the baisc MVVM structure, we are going to connect our MainViewModel to our MainPage. There are two ways to do so.

In Xaml:

<ContentPage.BindingContext>
    <Binding Path="MainVm" Source="{StaticResource Locator}" />
</ContentPage.BindingContext>

in Code:

        public MainPage()
        {
            InitializeComponent();

            this.BindingContext = ViewModelLocator.Instance.MainVm;
        }

After that, just use the HelloWorldString property of the MainViewModel as Text in the already existing Label:

    <Label Text="{Binding HelloWorldString}"
           VerticalOptions="Center"
           HorizontalOptions="Center" />

Before we are able to test our code, we need to make sure our ViewModelLocator is initialized properly:

Android:

    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
            //TabLayoutResource = Resource.Layout.Tabbar;
            //ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(bundle);

            global::Xamarin.Forms.Forms.Init(this, bundle);

            ViewModelLocator.Instance.Initialize();

            LoadApplication(new App());
        }
    }

iOS:

    [Register("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {
        //
        // This method is invoked when the application has loaded and is ready to run. In this 
        // method you should instantiate the window, load the UI into it and then make the window
        // visible.
        //
        // You have 17 seconds to return from this method, or iOS will terminate your application.
        //
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();

            ViewModelLocator.Instance.Initialize();

            LoadApplication(new App());

            return base.FinishedLaunching(app, options);
        }
    }

UWP:

//in App.xaml.cs:
        protected override void OnLaunched(LaunchActivatedEventArgs e)
        {

#if DEBUG
            if (System.Diagnostics.Debugger.IsAttached)
            {
                this.DebugSettings.EnableFrameRateCounter = true;
            }
#endif

            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                rootFrame.NavigationFailed += OnNavigationFailed;

                Xamarin.Forms.Forms.Init(e);

                ViewModelLocator.Instance.Initialize();

                if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    //TODO: Load state from previously suspended application
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                rootFrame.Navigate(typeof(MainPage), e.Arguments);
            }
            // Ensure the current window is active
            Window.Current.Activate();
        }

Let’s test our app on all platforms by building and deploying them:

Android

iOS Screenshot – post will be updated 

UWP

If you get the same screens, you are all set up to use Xamarin Forms with MVVMLight.

Conclusion

I know there are several specialized MVVM frameworks/toolkits floating around, which are commonly used for Xamarin Forms. As I am quite used to the MVVMLight toolkit, I prefer it over them. It is a lightweight solution, and I have more control over the code that is running than with the other options. I know I have to handle a lot of things in this case on my own (Navigation for example), but these will get their own blog posts. Starting with one of the future posts in this series, I will provide a sample app on my Github account.

If you have feedback or questions, feel free to get in contact with me via comments or on my social accounts. Otherwise, I hope this post and the following ones are helpful for some of you.

Happy coding, everyone!

Posted by msicc in Android, Dev Stories, iOS, Xamarin, 12 comments

Xamarin: Android Activities, Context, Intents and Views

xamandroid

If you are coming from C#/Silverlight, Android can be a little diffusing. Android does not have the same structure than a Windows or Windows Phone app.

Activities

Android has Activities. Activities are the key classes of Android were all actions take place. Unlike other apps or programs, you do not have a “Main” program that is your starting point when launched.

In Android, the starting point is an Activity. The Activity needs to be declared as the starting point. When you start a new project in Xamarin, an Activity called “MainActivity” gets created automatically.

This Activity has some attributes:

[Activity (Label = "gettingstarted", MainLauncher = true)]

The ‘Label’ attribute is what you will see in the Title bar when launching the app. The attribute ‘MainLauncher=true’ tells the application to start from here. Think of this as your MainPage.xaml.cs in a Windows Phone app.

Every Activity has its own OnCreate event, where you can put all your starting, button handlers, stylings etc. in.

But an Activity still has more. It has events like OnStart(), OnPause(), OnRresume() and OnStop() and OnDestroy() and OnRestart(). I won’t get into deep this time, as the Xamarin documentation has already a very good overview of those events: http://docs.xamarin.com/guides/android/application_fundamentals/activity_lifecycle/.

Those events are important to understand for a lot of your application logic, like:

  • saving data that has to be persistent
  • starting and pausing animations
  • register and unregister external events
  • fetch data that are passed from other Activities
  • and more (we will cover some of them in my further posts)

I absolutely recommend to go to the link above to read and understand those events.

Context

The Context is often needed in an Android application and allows your code to be run within an Activity.

The Context allows you for example:

  • to access Android services,
  • to access Application resources like images or styles,
  • to create views
  • to assign gestures to an Activity

Without Context, often code does not get accepted by the IDE or makes your code getting ignored while running the app. Luckily, all methods that I used so far have been telling me if they want a Context, so you need only learn to find out if you need Context for the Activity resources or Application resources.

Intents

But what if we want to have another page (like a separate about page for example)? How can we navigate between pages or call external functions?

This is what Intents are for. Intents are sending messages through the application if another function needs to be started, like the launch of a second page. Within these intents, we have declare the actions that the app needs to do, and if we need a callback, this will also be passed with an Intent.

Let’s hold this high level, here are some lines of code that navigate to a second page (Activity):

var second = new Intent(this, typeof(SecondActivity)); StartActivity(second);

With this code, we are creating an new Intent with Context to our current running Activity to launch the SecondActivity.

To send data between Activities, we use the PutExtra() method of Intents:

var second = new Intent(this, typeof(SecondActivity)); 

second.PutExtra("FirstPage", "Data from First Page"); 

StartActivity(second);

Of course, we need also some code to read the passed data on our second page:

Intent.GetStringExtra("FirstPage") ?? “Data not available”;

We could now use this data on our second page by assigning it to a control or function.

Passing data between activities works similar to passing QueryStrings in NavigationsService.Navigate() method on WindowsPhone, so you should get familiar with it very fast.

Views

The last part that is very important are Views. In a View you declare how the Activity looks like. Think of it as your MainPage.xaml page in a Windows Phone app.

Views can be very different, too. Let’s start with the simple View. In our getting started project, we also have a Layout file that holds our first View:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/myButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
</LinearLayout>

The View has a main LinearLayout which is acts as  ContentPanel. All other controls like Buttons, TextViews etc. are going into this. There are a lot of properties that can be set, we’ll leave it this easy for now. If you want to know more about those properties, you can have a look at the Android documentation here: http://developer.android.com/guide/topics/ui/declaring-layout.html

This part is totally the same as with the one matching part in the Android SDK, so you will need to get familiar with the Android documentation as well.

To make a View visible, we need to assign it to an Activity. In our sample app, we are doing this with this line of code in our OnCreate event:

SetContentView (Resource.Layout.Main);

This is the easy way for Views. But there are more complex Views in Android, too.

Views are also used in ListViews, where you declare the look of the items and the list in a Layout file, or also if you use the ActionBar with a tab navigation, and also in the menu of an ActionBar. I will cover all of these in my further blog posts, as we also need Adapters to get data binded to Views.

I hope you this post helps you to understand  the high level structure of an Android application.

Until the next time, happy coding!

Posted by msicc in Android, Dev Stories, Xamarin, 0 comments

Xamarin: Resources of an Android app project

As I mentioned already in my first blog post about Xamarin, Android has a different project structure – even if you use Xamarin.

A very important part of this structure are resources. We have different kind of resources in an Android app:

  • Icons & Images
  • Layout (XML files)
  • Values (string resource files)

Let’s start with Icons & Images.

As you can see in the solution window, there is a folder called ‘Resources’. Here you will put all kind of resources, like images, icons, layouts and so on.

The corresponding class for images in Android is called ‘drawable’, that holds a reference to’ Icon.png’. The project structure is based on that, that’s why the resources folder has all images inside the folder ‘drawable’. As Android has various screen sizes, you may have a folder for structure like ‘drawable’, ‘drawable-hdpi, ‘drawable-ldpi’ and so on. Android scales your image resources to match the screen automatically if you do not define alternate layouts.

To make your files available in your app, you need to set the Build Action to ‘Android Resource’:

Screenshot (278)

Let’s have a look to the Layout files:

Layout files are XML files that contain the UI of a page, control or a view. You can use these XML files for example to define items of a ListView or simply the application page. Every new project has a ‘Main.axml’ file.

There are two ways to create a layout. The first one is using the visual designer:

Screenshot (280)

This works for basic layouts like adding the button above. Also, if you don’t know the properties of a control you added, you will be able to add it here to get started.

If you are familiar with writing your UI in code (like XAML)  and want to do so in your Android app, just click the ‘Source’ tab at the bottom in the visual designer. You will see something like this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/myButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
</LinearLayout>

If you want to add and modify a control, but don’t know how the properties are, this page has a list of all controls, which are called ‘widgets’ in Android. That’s also the corresponding namespace: android.widget.

Like in an Windows Phone app, you also have a string resource file in Android projects. This file is once again a XML file, but with a different structure:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, Click Me!</string>
<string name="app_name">gettingstarted</string>
</resources>

All strings need to be declared inside the <resources> tag. The definition is always like <string name=”yourstringname”>stringcontent</string>. Empty strings are not supported and will throw an error at building your project.

Let’s have a look on how we can work with our resources, based on our gettingstarted project. We have the following code inside our MainActivity class:

int count = 1;

		protected override void OnCreate (Bundle bundle)
		{
			base.OnCreate (bundle);

			// Set our view from the "main" layout resource
			SetContentView (Resource.Layout.Main);

			// Get our button from the layout resource,
			// and attach an event to it
			Button button = FindViewById<Button> (Resource.Id.myButton);
			button.Text = GetString (Resource.String.hello);

			button.Click += delegate {
				button.Text = string.Format ("{0} clicks!", count++);
			};
		}

As you can see, the we are defining our view from our Layout file ‘Main.axml’ by using the SetContentView() method. The file is added to our resources list as Layout with the name we defined.

Our MainActivity does not know that we have a button inside our layout. To make the button visible to our MainActivity, we need to reference it. This is done by declaring a Button instance and using the FindViewById<T>(ResourceName) method.

If you have not given your button a name, now is the right time to do so. In our example the button has the name “myButton”.  The syntax is very important, make sure you add “@+id/” to the name.

android:id="@+id/myButton"

Now our button is visible to our MainActivity code page and can be accessed. The sample project references the button content in the Layout file:

android:text="@string/hello"

After referencing our button, we could also use the following code to get the button content from the resource file:

button.Text = GetString (Resource.String.hello);

Whenever your want to get a string from the resource file in an Activity, the GetString() method is used.

I hope this post helps you to understand how resources are used in an Android app and how to handle it a Xamarin project.

Happy coding everyone!

Posted by msicc in Android, Dev Stories, Xamarin, 0 comments

Xamarin: how to set up an Android device for Debugging

Xamarin comes with some emulators for development of an Android app. While these emulators are working and are also available in all supported screen sizes, the performance of them is really bad.

That’s why I chose debugging via device, which is a lot faster than the emulators once you have the required Xamarin extensions installed.

Here is how to set up an Android device for debugging. First thing you need to know is which OS version is running. On most Android devices, you will find this information under Settings/About (or Info)/Software information. If you don’t have the result there, you should check the manual where to find this information on your device.

Screenshot_2013-12-29-07-03-31

Activate Debugging until Android 3.2

  • go to Settings from your Application Menu
  • choose Applications
  • open the Development item
  • you will see now the option to activate USB debugging:

Android_debug_until_32

Activate Debugging on Android 4.0, 4.1

  • go to the Settings Menu
  • choose Developer options and activate USB debugging:

Android_debug_until_32

Activate Debugging on Android 4.2 and higher

  • go to the Settings Menu
  • select About
  • tap the Build Number 7 times (after the 4th tap a notification will appear that counts down the required taps)

Screenshot_2013-12-29-07-04-36

 

Installing drivers

Now our devices are ready to be connected to our PC, where we need to install the corresponding USB drivers. Normally you just need to plug in your Android device, Windows will search for the right driver and install it for you. If you want to install the driver manually, here is a list of OEM driver packages: http://developer.android.com/tools/extras/oem-usb.html#Drivers

Deploying an App for debugging

After the drivers have been installed, your device should now be recognized by Windows and also by Xamarin Studio.

Using our gettingstarted project from my first blog post, you should have now two options to deploy the application to your device:

Run With…

Screenshot (273)

Just hit ‘Debug’…

Screenshot (275)

Xamarin Studio installs now the required packages for debugging, and after that, you will be able to debug you application.

Speeding up re-deployments

Xamarin will install all developing packages including your app from scratch every time you deploy the app. To speed things up, there is an option to speed things a little up.

To activate/check if this option is already activated, click on the ‘options’ button of your project and select ‘Options’ in the context menu:

Screenshot (276)

Select ‘Android Build’ and activate these two options:

Screenshot (276)

 

This way, Xamarin will deploy only changes that have been made to your code, while keeping the required packages on your device. Xamarin Studio will detect if an update to those packages is required.

However, sometimes you will need to clean your solution and do a complete re-deploy (like you are doing with a Windows Phone project sometimes, too).

In very seldom cases (happened 3 times to me by now), you will need to uninstall your app and all of the Xamarin packages from your device. To do so, go to Settings/Apps on your device. In the application list, you will find some apps that start with ‘Mono’:

Screenshot_2013-12-29-07-57-13

To uninstall them, tap the items and select ‘Uninstall’ in the App info screen:

Screenshot_2013-12-29-07-58-43

 

Xamarin Studio will now re-deploy all required packages to your device, and your app should run again for debugging.

Like always, I hope this post is helpful for some of you.

Happy coding!

Posted by msicc in Android, Dev Stories, Xamarin, 2 comments

New Series: developing for Android with Xamarin

xamandroid

Prolog

In the last few month I was developing not only my personal projects, but also on my daily 9to5 job. I am working on an internal app that will help to improve the customer experience amongst the customers of my employer Telefónica.

The project has a simple setup in phase I, with collecting data and sending them via mail. The challenge for me was how to get the Windows Phone app (yes, Windows Phone was first!) to Android.

I knew it would take some time to get started with Android development, and was searching for possible solutions to speed things up. I knew from Xamarin already, and was able to obtain a 1-year license for Android (maybe iOS will follow later).

Some of my fellow WinPhans and WinPhanDevs will scream out very loud at the moment. I understand that. But honestly, I could not let go away this huge opportunity for me – as it touches both my daily job and my private developer story. To calm you down: I will always love Windows Phone and Windows and develop for it first. I will always remain a WinPhanDev. But I need to go forward, and this is a big step.

Let’s go back to the topic.

With this blog post, I am kicking off a new blogging series for Android development with Xamarin. The huge advantage of using Xamarin is that I am able to use my C# knowledge to develop apps for other platforms – which makes it a little easier to get things done.

However, if you start with another platform, you still have to learn the platform structure. Without knowing or be willing to learn it, you will be lost very fast. Every OS has its own specific UI rules, save handling and so on. This is what I will blog about.

The Windows Phone app I ported to Android has a item Pivot, which I ported over to Android. It has a little different appearance, but it works in a similar way with tapping the header or a swiping gesture to move between the items/pages.

To get there, I had to learn a lot about Android – and I will share it all with you out there.

My series will cover the following topics:

Installing Xamarin

Installing Xamarin is pretty easy – but will take some time. Click on this link to download the Xamarin IDE. The IDE will ask you for which platform you want to develop for (let’s choose only Android for the moment) and then download a huge amount of additional SDKs like the Java and the Android SDK (Android apps are Java based, if you didn’t knew).

Screenshot (267)

On the screenshot above you can see the starting page of Xamarin Studio. On the left side you have the list of recent solutions, in the middle you see Xamarin news and finally the pre-built apps section.

Xamarin Studio has a lot together with Visual Studio, and you also can take a lot of settings to adjust the appearance for your needs. Let’s start a new project by clicking on the ‘New’ button

Screenshot (270)

Xamarin will set up a .sln file with everything we need for the moment. After creating the project has been created, you’ll see these lines of code:

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace gettingstarted
{
	[Activity (Label = "gettingstarted", MainLauncher = true)]
	public class MainActivity : Activity
	{
		int count = 1;

		protected override void OnCreate (Bundle bundle)
		{
			base.OnCreate (bundle);

			// Set our view from the "main" layout resource
			SetContentView (Resource.Layout.Main);

			// Get our button from the layout resource,
			// and attach an event to it
			Button button = FindViewById<Button> (Resource.Id.myButton);

			button.Click += delegate {
				button.Text = string.Format ("{0} clicks!", count++);
			};
		}
	}
}

 

These few lines should help to get started with the basic structure of an Android App.

Android has Activities. Activities can be seen as the code behind files in a C# project. Here begins all the action of an Android app. Xamarin automatically ads the Label (project name) and in this case, also the MainLauncher property, which will run this code on app start up.

To get something displayed in our app, we need to load a Layout or create the view from the code. This is what the SetContentView() method is about. Without this, the app will compile but displays nothing. In this demo app, a basic layout with a button inside is created:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <Button
        android:id="@+id/myButton"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
</LinearLayout>

 

We already have the first difference to other C# projects here. In order to make the button visible for our code in the Activity, we need to search our resources for the button. This is done by the FindViewById<T>() method. As soon as it is visible to our code, we are able to create a delegate for our button Click event.

The button counts then the clicks on it and changes the text based on the number of clicks.

To understand more about the structure of an Android App, I highly recommend to read the documentation. For me, especially these links were helpful:

There are some more resources that are helpful, but for getting started those four links should be enough. I will cover some of the topics above also with my upcoming posts and link additional resources as well.

As with the Windows Phone development, also StackOverflow is a big help as well as the Xamarin  Android forums.

Until the next post, happy coding!

Posted by msicc in Android, Dev Stories, Xamarin, 0 comments