No need custom renderers

Xamarin Forms power

I’ve heard so many people saying you can’t do a lot of things with Xamarin Forms. To all of them, I say bullshit :D

You can do almost everything you want with Xamarin Forms. You may have some hard times but no pain no gain ;)
If you combine animations and images and the build in controls, you won’t required a lot of custom renderers.

As an example: let’s say you need a custom renderer because the watermark of the Entry control doesn’t work on a specific platform. If you want to get rid off the custom renderer, you can create your own control! A view composed of a Label which is over an Entry. When the Label or the Entry is focused, you hide the Label. You don’t show it unless it lost the focus and that the Entry text isn’t empty or not equal to the watermark text. End of the story :)

Image power

My best friend is a developer too. We met each other at school. But he took the Javascript path while I chose C#. He went on Titanium while I went on Xamarin. When we compared the mobile app we’ve developed, I was, most of the time, a bit jealous of how beautiful his apps were. I thought he might be a CSS expert! But most of the time, he was just using amazing images, cool icons and cool fonts. He had a designer in his development team while I didn’t (I used to work on business app). The fast you can trade with your designs, the better the integration will be. I think that designers and developers worked better together if they are in the same team.

Sometimes, what takes you a minute to do in Inkscape or Illustrator may take tons of times with code. It’s very easy to create a very cool button background with an image. How will you get an amazing look with the common stuff like a border, a background color and a padding ? ^_^
With an image, it’s very easy. If you have a good designer, he can even realize amazing buttons, amazing icons. My friends just add to perform some little animation on the image and boom! His UI looks very great with few work!

Check out this code:

<Grid>
    <Image Source=PictoBackgroundCircle.png />
    <Image VerticalOptions=Center
        HorizontalOptions=Center
        Source={Binding Source, Mode=OneWay} />
</Grid>

And yea, you get a new button ready to use and easy to customize. You can even bind a background image source too.

A last word, image a cross platform and cross everything :D they can be added in a Website, a mobile app, a desktop app, an email. Everything! While a Xamarin Forms equivalent code works…only with Xamarin Forms. Even if the Xaml can be easily port on a Microsoft Xaml based project, it’s still not the most portable.

Now, I don’t think too much when I have to do something that can be easily drawn in Inkscape. This incredible software allows you to export your file into XAML!!! You might give this software a shot! I use it to perform my icons, shapes that would be hard or boring to do in code.


SDF – Map – Pin & Map clicked

If you saw my older post, you have seen that nothing were display when a click is made on a pin or the map.

It was very easy to implement a menu popup when a pin is displayed. Again, thanks to the amazing Xamarin Forms API, it was very easy to animate the popup. It works very well in iOS and Android. This animation was far easier than animating the user panel on the home page. If you don’t change the layout position of a control, its animation render fast enough to increase the user experience. Yea, sometimes an animation can affect the user experience.

Here is a screenshot of the animation. Notice that I use a Grid as the root element. The main reason is that I use the Z-Index style :D it means that the second child of the Grid will be displayed over the first child. Thus, I don’t need to bother anything. Playing with the visibility of the ContentView named PanelActions is enough.

Xaml of the AroundMePage.

Xaml of the AroundMePage.

In the code behind, I launch the animation whenever the property IsMapActionsVisible has changed. It’s not recommended to use Messenger for this purpose. Avoid using Messenger as it’ not the most efficient way to do things. It may be productive and easier to use Messenger sometimes. But if you use the Messenger pattern in a view to register somethings that came from the view model which it’s binded to, you may go in the wrong way.

C# of the AroundMePage.

C# of the AroundMePage

The result in a GIF: if you pay attention, I’ve handled the tapp out of the popup to cancel and close it. It is very boring when a popup doesn’t behave like that. If my popup would have been bigger, I would have add a close button because on low resolution screen, the map may be unclickable.

SDF Map clicked, pin clicked

SDF Map clicked, pin clicked


SDF – Development – design updated

I wanted to show you the work I did so far. I know, I still have a lot of work to make this app looking better :)

But it is still in development :D

It wasn’t hard to create an extended map control that exposes a CurrentLocation bindable property and also a Locations bindable property. This control has 2 commands : CommandMap and CommandPin. Right now, I just show a dialog. I had to create a custom renderer to raise the PinClicked event which isn’t available from Xamarin Forms. If you just need to display some pins on the map, you won’t need a custom renderer.

Don’t forget to specify a label for every pin you add. Without a label, the small white popup won’t display and thus, prevent any click event. Plus, it’s required on a platform (I think it was Android) if you don’t specify the Label, it will crash. You have to set string.Empty at least but even if it doesn’t crash anymore, it sill won’t display the popup. You have to pass a string not empty to enable the raising of the click event.

Here is how I use it in my Xaml :

The ExtMap control inside a page in Xaml.

Here is the result:

If you pay attention, once the map is displayed there are 3 pins displayed and then a 4th pin is added. It’s just to show that my ObservableCollection of Location works ;) It was the first time I create a Xamarin Forms control that use an observable collection and listen its CollectionChanged event. I will use this method to create my ItemsControl of T where T inherits from a ContentView. Xamarin Forms is missing a repeater view control. I know there is the XLab Repeater View. But don’t ask me why, I don’t want to add too many dependencies. Even more for my user interface controls. And I love so much to create my own controls that I don’t want to rely on someone else ;)

 

The GIF of the SDF app.

The SDF app presentation.


ExtWebView

My custom WebView. It has a HTML string property. This was very useful to draw my chart :) a simple HTML file with some embedded Javascript to draw the shapes. It was the faster way for me to make a cross pie chart control. When the HTML property has changed, the source of the WebView gets updated.

//
// <copyright file=ExtWebView.cs company=Krossapp>
//     Copyright (c) Krossapp. All rights reserved.
// </copyright>
// <author>Nicolas Krier</author>
//
namespace SDF.XForm.Controls
{
    #region Using

    using System.Diagnostics.CodeAnalysis;
    using System.Windows.Input;
    using Xamarin.Forms;

    #endregion

    /// <summary>
    /// Web view.
    /// </summary>
    public class ExtWebView : WebView
    {
        #region Bindable property

        /// <summary>
        /// The html property.
        /// </summary>
        [SuppressMessage(StyleCop.CSharp.MaintainabilityRules, SA1401:FieldsMustBePrivate, Justification = Reviewed.)]
        public static BindableProperty HtmlProperty = BindableProperty.Create<ExtWebView, string>(x => x.Html, null, BindingMode.OneWay, propertyChanged: WhenHtmlChanged);

        /// <summary>
        /// The command clicked property.
        /// </summary>
        [SuppressMessage(StyleCop.CSharp.MaintainabilityRules, SA1401:FieldsMustBePrivate, Justification = Reviewed.)]
        public static BindableProperty Command = BindableProperty.Create<ExtWebView, ICommand>(x => x.CommandClicked, null);

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref=ExtWebView/> class.
        /// </summary>
        public ExtWebView()
            : base()
        {
            this.HandleTapEvent();
        }

        #endregion

        #region Property

        /// <summary>
        /// Gets or sets the html.
        /// </summary>
        /// <value>The html.</value>
        public string Html
        {
            get { return (string)this.GetValue(HtmlProperty); }
            set { this.SetValue(HtmlProperty, value); }
        }

        /// <summary>
        /// Gets or sets the command clicked.
        /// </summary>
        /// <value>The command clicked.</value>
        public ICommand CommandClicked
        {
            get { return (ICommand)this.GetValue(Command); }
            set { this.SetValue(Command, value); }
        }

        #endregion

        /// <summary>
        /// Raises the html changed event.
        /// </summary>
        /// <param name=sender>The sender.</param>
        /// <param name=oldValue>Old value.</param>
        /// <param name=newValue>New value.</param>
        private static void WhenHtmlChanged(BindableObject sender, string oldValue, string newValue)
        {
            WebView ctrl = (WebView)sender;
            ctrl.Source = new HtmlWebViewSource() { Html = newValue };
        }

        /// <summary>
        /// Handle the tap event : the click.
        /// </summary>
        private void HandleTapEvent()
        {
            /*
            var tapGestureRecognizer = new TapGestureRecognizer();
            tapGestureRecognizer.Tapped += (sender, args) =>
            {
                if (args != null && this.CommandClicked != null && this.CommandClicked.CanExecute(args))
                {
                    this.CommandClicked.Execute(args);
                }
            };
            this.GestureRecognizers.Add(tapGestureRecognizer);
            */
        }
    }
}


ExtSwitch

My custom switch control. This control is kind of useless right now. I don’t use to bind a command on a switch. Even more if the switch is used in a ListView because I may handle the tap event on a bigger area than just the switch itself.

//
// <copyright file=ExtSwitch.cs company=Krossapp>
//     Copyright (c) Krossapp. All rights reserved.
// </copyright>
// <author>Nicolas Krier</author>
//
namespace SDF.XForm.Controls
{
    #region Using

    using System.Diagnostics.CodeAnalysis;
    using System.Windows.Input;
    using Xamarin.Forms;

    #endregion

    /// <summary>
    /// The Switch.
    /// </summary>
    public class ExtSwitch : Switch
    {
        #region Bindable property

        /// <summary>
        /// The command toggled property.
        /// </summary>
        [SuppressMessage(StyleCop.CSharp.MaintainabilityRules, SA1401:FieldsMustBePrivate, Justification = Reviewed.)]
        public static BindableProperty CommandToggledProperty = BindableProperty.Create<ExtSwitch, ICommand>(x => x.CommandToggled, null);

        /// <summary>
        /// The command parameter toggled property.
        /// </summary>
        [SuppressMessage(StyleCop.CSharp.MaintainabilityRules, SA1401:FieldsMustBePrivate, Justification = Reviewed.)]
        public static BindableProperty CommandToggledParameterProperty = BindableProperty.Create<ExtSwitch, object>(x => x.CommandToggledParameter, null);

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref=ExtSwitch/> class.
        /// </summary>
        public ExtSwitch()
            : base()
        {
            // SubscribeClickToRaiseCommand();
            this.Toggled += this.OnItemSelected;
        }

        #endregion

        #region Property

        /// <summary>
        /// Gets or sets the command toggled.
        /// </summary>
        /// <value>The command toggled.</value>
        public ICommand CommandToggled
        {
            get { return (ICommand)this.GetValue(CommandToggledProperty); }
            set { this.SetValue(CommandToggledProperty, value); }
        }

        /// <summary>
        /// Gets or sets the command parameter toggled.
        /// </summary>
        /// <value>The command parameter toggled.</value>
        public object CommandToggledParameter
        {
            get { return (object)this.GetValue(CommandToggledParameterProperty); }
            set { this.SetValue(CommandToggledParameterProperty, value); }
        }

        #endregion

        /// <summary>
        /// Raises the item selected event.
        /// </summary>
        /// <param name=sender>The sender.</param>
        /// <param name=e>The event args</param>
        private void OnItemSelected(object sender, ToggledEventArgs e)
        {
            if (this.CommandToggled != null && sender.GetType() == typeof(ExtSwitch) && ((ExtSwitch)sender).CommandToggledParameter != null && this.CommandToggled.CanExecute(e) && e.Value)
            {
                this.CommandToggled.Execute(this.CommandToggledParameter);
            }
        }

        /// <summary>
        /// Subscribes the click to raise command.
        /// </summary>
        private void SubscribeClickToRaiseCommand()
        {
            var tapGestureRecognizer = new TapGestureRecognizer();
            tapGestureRecognizer.Tapped += (sender, e) =>
            {
                if (this.CommandToggled != null && this.CommandToggled.CanExecute(e))
                {
                    this.CommandToggled.Execute(this.CommandToggledParameter);
                }
            };
            this.GestureRecognizers.Add(tapGestureRecognizer);
        }
    }
}


ExtProgressBar

This control needs a custom renderer to use the ProgressColor. A custom renderer gives you the possibility to animate the progress bar on iOS when its progress value changes.

//
// <copyright file=ExtProgressBar.cs company=Krossapp>
//     Copyright (c) Krossapp. All rights reserved.
// </copyright>
// <author>Nicolas Krier</author>
//
namespace SDF.XForm.Controls
{
    #region Using

    using System.Diagnostics.CodeAnalysis;
    using Xamarin.Forms;

    #endregion

    /// <summary>
    /// Progress bar.
    /// </summary>
    public class ExtProgressBar : ProgressBar
    {
        #region Bindable property

        /// <summary>
        /// The progress color property.
        /// </summary>
        [SuppressMessage(StyleCop.CSharp.MaintainabilityRules, SA1401:FieldsMustBePrivate, Justification = Reviewed.)]
        public static BindableProperty ProgressColorProperty = BindableProperty.Create<ExtProgressBar, Color>(x => x.ProgressColor, Color.Blue);

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref=ExtProgressBar/> class.
        /// </summary>
        public ExtProgressBar()
            : base()
        {
        }

        #endregion

        #region Property

        /// <summary>
        /// Gets or sets the color of the progress.
        /// </summary>
        /// <value>The color of the progress.</value>
        public Color ProgressColor
        {
            get { return (Color)this.GetValue(ProgressColorProperty); }
            set { this.SetValue(ProgressColorProperty, value); }
        }

        #endregion
    }
}


ExtListView

I like to bind a command to my list view so I don’t have to create a wrapper to pass the item tapped command. I also deactivate the separator which behave very strange sometimes depends on the device. I prefer to handle it myself. I have added a DesactivateSelection property so once you’ve tapped an item, the command is executed and the item gets unselected.

I created this control before the pull to refresh and pull to load event were added to the list view. I still not have clean this control yet. It’s in my todo ;D

//
// <copyright file=ExtListView.cs company=Krossapp>
//     Copyright (c) Krossapp. All rights reserved.
// </copyright>
// <author>Nicolas Krier</author>
//
namespace SDF.XForm.Controls
{
    #region Using

    using System.Diagnostics.CodeAnalysis;
    using System.Windows.Input;
    using Xamarin.Forms;

    #endregion

    /// <summary>
    /// List view.
    /// </summary>
    public class ExtListView : ListView
    {
        #region Bindable property

        /// <summary>
        /// The command refresh property.
        /// </summary>
        [SuppressMessage(StyleCop.CSharp.MaintainabilityRules, SA1401:FieldsMustBePrivate, Justification = Reviewed.)]
        public static BindableProperty CommandRefreshProperty = BindableProperty.Create<ExtListView, ICommand>(x => x.CommandRefresh, null);

        /// <summary>
        /// The deselection auto property.
        /// </summary>
        [SuppressMessage(StyleCop.CSharp.MaintainabilityRules, SA1401:FieldsMustBePrivate, Justification = Reviewed.)]
        public static BindableProperty DesactivateSelectionProperty = BindableProperty.Create<ExtListView, bool>(x => x.DesactivateSelection, false);

        /// <summary>
        /// The command clicked property.
        /// </summary>
        [SuppressMessage(StyleCop.CSharp.MaintainabilityRules, SA1401:FieldsMustBePrivate, Justification = Reviewed.)]
        public static BindableProperty CommandProperty = BindableProperty.Create<ExtListView, ICommand>(x => x.Command, null);

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref=ExtListView/> class.
        /// </summary>
        public ExtListView()
        {
            this.SeparatorVisibility = SeparatorVisibility.None;

            // this.ItemTapped += this.OnItemTapped;
            this.ItemSelected += this.OnItemSelected;
        }

        #endregion

        #region Property

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref=ListView/> deselection auto.
        /// </summary>
        /// <value><c>true</c> if deselection auto; otherwise, <c>false</c>.</value>
        public bool DesactivateSelection
        {
            get { return (bool)this.GetValue(DesactivateSelectionProperty); }
            set { this.SetValue(DesactivateSelectionProperty, value); }
        }

        /// <summary>
        /// Gets or sets the command clicked.
        /// </summary>
        /// <value>The command clicked.</value>
        public ICommand Command
        {
            get { return (ICommand)this.GetValue(CommandProperty); }
            set { this.SetValue(CommandProperty, value); }
        }

        /// <summary>
        /// Gets or sets the command refresh.
        /// </summary>
        /// <value>The command refresh.</value>
        public ICommand CommandRefresh
        {
            get { return (ICommand)GetValue(CommandRefreshProperty); }
            set { this.SetValue(CommandRefreshProperty, value); }
        }

        #endregion

        /// <summary>
        /// Raises the item tapped event.
        /// </summary>
        /// <param name=sender>The sender.</param>
        /// <param name=e>The event args.</param>
        private void OnItemTapped(object sender, ItemTappedEventArgs e)
        {
            if (e.Item != null && this.Command != null && this.Command.CanExecute(e))
            {
                this.Command.Execute(e.Item);
            }
        }

        /// <summary>
        /// Raises the item selected event.
        /// </summary>
        /// <param name=sender>The sender.</param>
        /// <param name=e>The event args.</param>
        private void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
        {
            // We force the selected item so the view model can handle differents events.
            this.SelectedItem = e.SelectedItem;

            if (e.SelectedItem != null && this.Command != null && this.Command.CanExecute(e))
            {
                this.Command.Execute(e.SelectedItem);
            }

            if (this.DesactivateSelection)
            {
                this.SelectedItem = null;
            }
        }
    }
}


ExtImage

This is my image control. I have added a property that allows me to change the look of the control so it looks like it is desabled. You can also bind a command to it that will be executed on tapp on the image.

//
// <copyright file=ExtImage.cs company=Krossapp>
//     Copyright (c) Krossapp. All rights reserved.
// </copyright>
// <author>Nicolas Krier</author>
//
namespace SDF.XForm.Controls
{
    #region Using

    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Windows.Input;
    using Xamarin.Forms;

    #endregion

    /// <summary>
    /// The Button.
    /// </summary>
    public class ExtImage : Image
    {
        #region Bindable property

        /// <summary>
        /// The command property.
        /// </summary>
        [SuppressMessage(StyleCop.CSharp.MaintainabilityRules, SA1401:FieldsMustBePrivate, Justification = Reviewed.)]
        public static BindableProperty CommandProperty = BindableProperty.Create<ExtImage, ICommand>(x => x.Command, null);

        /// <summary>
        /// The command indicatique wether the image should be opaque or not.
        /// </summary>
        [SuppressMessage(StyleCop.CSharp.MaintainabilityRules, SA1401:FieldsMustBePrivate, Justification = Reviewed.)]
        public static BindableProperty IsImageOpaqueProperty = BindableProperty.Create<ExtImage, bool>(x => x.IsImageOpaque, false, propertyChanged: WhenIsImageOpaqueChanged);

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref=ExtImage/> class.
        /// </summary>
        public ExtImage()
            : base()
        {
            // this.SetBinding(ExtButton.IsEnabledProperty, new Binding(CanExecute, BindingMode.OneWay));
            this.SubscribeClickToRaiseCommand();
        }

        #endregion

        #region Property

        /// <summary>
        /// Gets or sets the command clicked.
        /// </summary>
        /// <value>The command clicked.</value>
        public ICommand Command
        {
            get { return (ICommand)this.GetValue(CommandProperty); }
            set { this.SetValue(CommandProperty, value); }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this image is opaque.
        /// </summary>
        /// <value><c>true</c> if this instance is image opaque; otherwise, <c>false</c>.</value>
        public bool IsImageOpaque
        {
            get { return (bool)this.GetValue(IsImageOpaqueProperty); }
            set { this.SetValue(IsImageOpaqueProperty, value); }
        }

        #endregion

        /// <summary>
        /// Raises the html changed event.
        /// </summary>
        /// <param name=sender>The sender.</param>
        /// <param name=oldValue>Old value.</param>
        /// <param name=newValue>New value.</param>
        private static void WhenIsImageOpaqueChanged(BindableObject sender, bool oldValue, bool newValue)
        {
            if (sender == null)
            {
                return;
            }

            var ctrl = (ExtImage)sender;
            ctrl.Opacity = newValue ? 0.25 : 1.0;
        }

        /// <summary>
        /// Subscribes the click to raise command.
        /// </summary>
        private void SubscribeClickToRaiseCommand()
        {
            var tapGestureRecognizer = new TapGestureRecognizer();
            tapGestureRecognizer.Tapped += async (sender, e) =>
            {
                if (this.Command != null && this.Command.CanExecute(e))
                {
                    uint duration = 100;
                    await this.ScaleTo(.75, duration);
                    await this.ScaleTo(1, duration);

                    this.Command.Execute(null);
                }
            };
            
            this.GestureRecognizers.Add(tapGestureRecognizer);
        }
    }
}


ExtHyperLink

This is my hyperlink control. I can use some generic style on it. This control must have the appearance of a classic html hyperlink. By default it behaves like a button. But it can also be used to open the default mailing app of the device. This control allows you to open a phone number in the dial screen. Last, this control can be used to open a location on the default map application of the device.

//
// <copyright file=ExtHyperLink.cs company=Krossapp>
//     Copyright (c) Krossapp. All rights reserved.
// </copyright>
// <author>Nicolas Krier</author>
//
namespace SDF.XForm.Controls
{
    #region Using

    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Windows.Input;
    using Xamarin.Forms;

    #endregion

    /// <summary>
    /// All kind of link types.
    /// </summary>
    public enum TypesLink
    {
        /// <summary>
        /// The default link : execute the command binded.
        /// </summary>
        Default = 0,

        /// <summary>
        /// The email.
        /// </summary>
        Email,

        /// <summary>
        /// The phone number.
        /// </summary>
        PhoneNumber,

        /// <summary>
        /// The location.
        /// </summary>
        Location
    }

    /// <summary>
    /// “Xamarin.Forms.Label” extended to get a kind of hyperlink.
    /// </summary>
    public class ExtHyperLink : Label
    {
        #region Bindable property

        /// <summary>
        /// The type link property.
        /// </summary>
        [SuppressMessage(StyleCop.CSharp.MaintainabilityRules, SA1401:FieldsMustBePrivate, Justification = Reviewed.)]
        public static BindableProperty TypeLinkProperty = BindableProperty.Create<ExtHyperLink, TypesLink>(x => x.TypeLink, TypesLink.Default);

        /// <summary>
        /// The command clicked property.
        /// </summary>
        [SuppressMessage(StyleCop.CSharp.MaintainabilityRules, SA1401:FieldsMustBePrivate, Justification = Reviewed.)]
        public static BindableProperty CommandProperty = BindableProperty.Create<ExtHyperLink, ICommand>(x => x.Command, null);

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref=ExtHyperLink/> class.
        /// </summary>
        public ExtHyperLink()
            : base()
        {
            this.FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Xamarin.Forms.Label));
            this.LineBreakMode = Xamarin.Forms.LineBreakMode.TailTruncation;
            this.SubscribeClickToRaiseCommand();
        }

        #endregion

        #region Property

        /// <summary>
        /// Gets or sets the type link.
        /// </summary>
        /// <value>The type link.</value>
        public TypesLink TypeLink
        {
            get { return (TypesLink)this.GetValue(TypeLinkProperty); }
            set { this.SetValue(TypeLinkProperty, value); }
        }

        /// <summary>
        /// Gets or sets the command clicked.
        /// </summary>
        /// <value>The command clicked.</value>
        public ICommand Command
        {
            get { return (ICommand)this.GetValue(CommandProperty); }
            set { this.SetValue(CommandProperty, value); }
        }

        #endregion

        /// <summary>
        /// Subscribes the click to raise command.
        /// </summary>
        private void SubscribeClickToRaiseCommand()
        {
            var tapGestureRecognizer = new TapGestureRecognizer();
            tapGestureRecognizer.Tapped += (sender, e) =>
            {
                if (this.TypeLink == TypesLink.Default)
                {
                    if (this.Command != null)
                    {
                        Command.Execute(null);
                    }
                }
                else if (this.TypeLink == TypesLink.PhoneNumber)
                {
                    string numTel = this.Text.Replace(., string.Empty);
                    numTel = numTel.Replace( , string.Empty);
                    numTel = numTel.Replace(, string.Empty);
                    Device.OpenUri(new Uri(tel:// + numTel));
                }
                else if (this.TypeLink == TypesLink.Email)
                {
                    Device.OpenUri(new Uri(mailto: + this.Text));
                }
                else if (this.TypeLink == TypesLink.Location)
                {
                    Device.OpenUri(new Uri(geo: + this.Text));
                }
                else
                {
                    throw new NotImplementedException(SubscribeClickToRaiseCommand > TypeLink not implemented);
                }
            };
            this.GestureRecognizers.Add(tapGestureRecognizer);
        }
    }
}


ExtContentPage

This is the code of my base page. I use to set up a binding by default on a property called IsLoading. Thus, in my view models, I just have to change the value of the IsLoading property and my view will display the busy indicator of the page.

In the OnAppearing event of the ContentPage, I call the LoadViewModel method. I have an InitializeViewModel method which is intend to be called once. The LoadViewModel will be called each time the page appear on the screen.

//
// <copyright file=ExtContentPage.cs company=Krossapp>
//     Copyright (c) Krossapp. All rights reserved.
// </copyright>
// <author>Nicolas Krier</author>
//
namespace SDF.XForm.Controls
{
    #region Using

    using SDF.Core.ViewModels;
    using Xamarin.Forms;

    #endregion

    /// <summary>
    /// Content page base.
    /// </summary>
    public class ExtContentPage : ContentPage
    {
        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref=ExtContentPage/> class.
        /// </summary>
        public ExtContentPage()
            : base()
        {
            this.SetBinding(ExtContentPage.IsBusyProperty, new Binding(IsLoading, BindingMode.OneWay));
        }

        #endregion

        #region Property

        /// <summary>
        /// Gets the view model.
        /// </summary>
        /// <value>The view model.</value>
        public ViewModelBaseExt ViewModel
        {
            get
            {
                return this.BindingContext == null ? null : this.BindingContext as ViewModelBaseExt;
            }
        }

        #endregion

        /// <summary>
        /// Raises the appearing event and initialize the view model.
        /// </summary>
        protected override void OnAppearing()
        {
            base.OnAppearing();
            this.ViewModel.LoadViewModel();
        }
    }
}