Blog

Xamarin Forms Reusable Control Tutorial

Feb 14 2017

The Xamarin Forms app which I'm working on requires a timeline control for several different pages, and while the code is relatively simple, I want to make it reusable so that it remains consistent throughout the application. With UWP and WPF the solution is straightforward; create a UserControl.

For a WPF UserContol there are dozens of articles and hundreds of StackOverflow questions available to draw upon. But finding answers to questions on Xamarin Forms can be challenging at times. That is partly due to the technology changing so rapidly, but also because it hasn't been around nearly as long as WPF or UWP. Thankfully, Xamarin has some very helpful forums, which, after having spent some time searching for tutorials on creating UserControls for Xamarin came up empty, a post in the forums was promptly replied too, and I was directed to a couple tutorials, including a really good one by Red Pill Xamarin which you can find here:  https://redpillxamarin.com/2017/01/28/206-reusable-controls/ . The tutorial which I'm about to go over is really just a slightly different take on theirs, and I would encourage you read their blog for a deeper dive into some of the points which I’m only going to gloss over here

First things first. Let me explain what it is were going to do then we’ll write the code. We’ll start by creating a new Forms Xamarin View, then we’ll add the new bindable Picker which was released with version 2.3.4.184, then we’ll add a BindableProperty to our code behind, add some items to our picker, then we’ll consume our reusable control in one of our app’s ContentPage(s), and finally we’ll bind the SelectedItem value to our ViewModel for use in filtering our data based on the time period selected. For this tutorial I’m using Xamarin Forms 2.3.4.192 pre-2 and Prism 6.3.0 pre-1.

Start by creating a new Forms Xamarin View file. In my case I named it TimePeriodControl. In the TimePeriodControl.xaml.cs (codebehind) page you’ll want to add the following code:

 

using System;

using System.Collections;

using System.Collections.Generic;

using Xamarin.Forms;

 

namespace MyAppsNamespace.Controls

{

    public partial class TimePeriodControl : ContentView

    {

        public TimePeriodControl()

        {

            InitializeComponent();

 

            Items_Source = new List<string>()

            {

                { "Week" }, { "Month" }, { "Three Months" }, { "Six Months" }, { "YTD" }, { "Year" }, { "All" }

            };

        }

 

        public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(

                                                                        nameof(Items_Source),

                                                                        typeof(IList),

                                                                        typeof(Picker));

 

        public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create(

                                                                        nameof(Selected_Item),

                                                                        typeof(object),

                                                                        typeof(Picker),

                                                                        null);

 

        public List<string> Items_Source

        {

            get {return (List<string>)GetValue(ItemsSourceProperty);}

            set { SetValue(ItemsSourceProperty, value); }

        }

 

        public object Selected_Item

        {

            get { return (object)GetValue(SelectedItemProperty); }

            set

            {

                SetValue(SelectedItemProperty, value);            }

        }

    }

}

 

 

The BindableProperty is Xamarin’s version of WPF’s DependencyProperty, which if you are a UWP developer you probably know that it has been superseded by the INotifyPropertyChanged, although it should be noted that UWP controls still use DependencyProperty(s) behind the scenes for binding. A BindableProperty is significantly more difficult to wrap your head around than a plain old CLR object in the INotifyPropertyChanged world, as they are significantly more configurable than a bindable property using INotifyPropertyChanged.

In each of the two cases above we are associating a BindableProperty with a CLR property below. We call the Create method and pass in several parameters including the name of the CLR property using the new C#6 keyword nameof(Items_Source) instead of just a string “Items_Source”. I intentionally named the property similar to the actual binding property, but different so that I could easily distinguish between the two later on while making the binding in the ContentPage which will consume the control.

We also set the type of the property for the type of control which we are using, note, that in this case I’ve set the ItemsSourceProperty to typeof(IList), while in the property I’m using List<string>. Next we set the type of control which we are using, in our case it will be typeof(Picker). Lastly, we’ll set a default value. In the case of the ItemsSourceProperty I’m setting my list in the classes’ constructor, while in the SelectedItemProperty I’m setting it to null. I should point out that there are additional configurations available for the BindableProperty which you may need to consider especially if you are going to be using dynamic content.

Next you’ll need to create the associated bindable properties. This is fairly straightforward, just make sure to use the correct type and keywords, and match the names to the BindableProperty.

Let's add a Picker to ourTimePeriodControl.xaml page like so:

 

<?xml version="1.0" encoding="UTF-8"?>

<ContentView xmlns="http://xamarin.com/schemas/2014/forms"

             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"

             x:Class="MyAppsNamespace.Controls.TimePeriodControl"

             x:Name="TimePeriodControlContentView">

  <ContentView.Content>

        <Picker Title="Time Filter"

                ItemsSource="{Binding Source={x:Reference TimePeriodControlContentView}, Path=Items_Source}"

                SelectedItem="{Binding Source={x:Reference TimePeriodControlContentView}, Path=Selected_Item}">

        </Picker>

    </ContentView.Content>

</ContentView>

 

Notice that I gave the ContentView a name, this is so that we can reference it in our bindings. I like to give any xaml control which I’m going to name, a meaningful name which will help me remember what it is. Names are hard, but naming consistently throughout your app is harder still. Typically, I’ll end up changing my naming scheme a couple times by the time that I’ve reached my third or fourth page, which then forces me to go back and correct my early work. The sooner that you adopt a standardized naming scheme the fewer changes you’ll have to make. Pick something which makes sense to you and which follows accepted naming conventions and stick to it.

Also note, that I could have created the Picker in code, and or set the Picker’s items in xaml.

Next, we’ll want to consume the control in one of our app’s ContentPages like so:

 

<?xml version="1.0" encoding="utf-8" ?>

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"

             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"

             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"

             prism:ViewModelLocator.AutowireViewModel="True"

             xmlns:controls="clr-namespace:MyAppsNamespace.Controls"

             x:Class="MyAppsNamespace.Views.AppCrashes">

 

           

    <Grid>                   

        <StackLayout>                           

            <controls:TimePeriodControl SelectedItem="{Binding TimePeriodSelectedItem, Mode=TwoWay}" />                       

        </StackLayout>               

    </Grid>

</ContentPage>

 

The key here is to make sure that you correctly add a reference at the top of your xaml file to the folder where you located your TimePeriodControl. In my case I named it “controls”, but you can name it whatever you like.

Next use that keyword “controls” to call the TimePeriodControl, and here, bind a property in our viewmodel to the actual Picker binding property. We're interested in finding out what the user selected and using that in our viewmodel to filter data on, so we use the SelectedItem property, making sure that we choose TwoWay binding so that the control can update our bound property.

Lastly, we just need to add the property to our viewmodel like so:

 

        private object timePeriodSelectedItem;

        public object TimePeriodSelectedItem

        {

            get { return timePeriodSelectedItem; }

            set { SetProperty(ref timePeriodSelectedItem, value); }

        }

 

In my case I’m using Prism as my viewmodel helper library, and this is the syntax for correctly creating a property. Other helper libraries will use a slightly different pattern. If you are using Prism remember to type in propp and hit the tab button twice to save you from having to write out all of that code by hand. No developer wants to brag about the number of times they’ve typed get and set!

I'm a C# application developer focused on cross platform mobile apps using the Xamarin solution.

Prior to teaching myself to code, I worked in the IT field as a small business owner, IT Systems Administrator, and website designer.

Resources

P.O. Box 1976, Myrtle Creek, OR 97457   ♦   (541) 375-0880      ♦   mgarcia@lacodiatech.com