May 22, 2019

Write your own Custom Controls for Xamarin.Forms

So why would you need to write a custom control for Xamarin? Does it have a purpose other than wrapping native controls that don’t exist in Xamarin? Why yes, it does serve a good purpose. I often will write a component to avoid having to copy and paste XAML repeatedly.

How do we create one?

I am going to assume you already have a project started in this post. I often create a directory/namespace called Controls in my PCL for this purpose. In any case, right click in your solution in Visual Studio’s PCL project and click Add, and then New Item.

add-newIn the window that appears, select Xamarin.Forms on the left hand side and then select Control View. Be sure you select Control View without the C# at the end of the label, unless you really want to do things manually. Name your control whatever you wish, for this demo I am naming it MyCustomControl.

imageYou should now have a the control available to insert into your application. By default, it should include a a StackLayout with a label inside of it. Next we are going to connect it to our applications XAML.

Add your component

Back in your page, we need to tell Xamarin how to find our custom control. To do this we add the following to our parent node:

xmlns:control=”clr-namespace:CustomControlsDemo.Controls”

The first section of this command says we are connecting to a specific namespace to use. The next portion gives it a name, you can use any that you want that is not currently in use and fits the requires of XAML. With the most recent versions of Visual Studio, intellicode will autocomplete a lot of this for you. Inside the quotes is telling the XAML to look at a .Net namespace and where exactly to find the control.

image-1Now that we have this added, Visual Studio can now list any components it can see. Unlike a basic control that you might add like a label, we need to put the “control” like we did with the parent node in front of the control we want to put in. In this case, we will type in control:MyCustomControl</control:MyCustomControl> as shown below. If you have done this correctly, and have your previewer enabled you should see the results instantly.

image-2

Adding custom properties

Now this is pretty simple but kind of useless as it stands right now. So how do get those properties like the rest of the Xamarin controls do? We add a custom property.

For this example, we are going to connect the font size to the property inside of our custom control. But we are going to modify the control to look a little more useful. Below is how I am going to adjust the control, you should modify it how you want to.

<?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="CustomControlsDemo.Controls.MyCustomControl">
    <ContentView.Content>
        <StackLayout>
            <Label>
                <Label.FormattedText>
                    <FormattedString>
                        <Span Text="Hello "/>
                        <Span x:Name="Person"></Span>
                        <Span Text=", and congratulations on your first custom control"/>
                    </FormattedString>
                </Label.FormattedText>
            </Label>
        </StackLayout>
    </ContentView.Content>
</ContentView>

Next I am going to create custom properties that directly interact with the Person span inside of our custom control. Goto the code side for your custom control, in windows I believe F7 will take you there.

We are going to create a string property called PersonName on our code that looks like the following. All it needs to do is translate text to and from our span inside of our control.

        public string PersonName
        {
            get => Person.Text;
            set => Person.Text = value;
        }

Now this would be all you would need if you were doing this entirely in C#, but we are not. So the next thing we need to do is create a static property that will define our property for XAML.

        public static readonly BindableProperty PersonNameProperty =
            BindableProperty.Create(
                nameof(PersonName),
                typeof(string),
                typeof(MyCustomControl),
                "No one",
                propertyChanged: PersonNameChanged);

The above code creates a static property. Using the static method Create inside of the BindableProperty object we define the property.

The first parameter in Create is the name of the property. You could technically put a string in here, but I prefer to use the nameof tool to return a name of the internal property.

The second parameter is the datatype that will be returned or passed into the bindable property. In this case, we are using a string.

The next parameter is the declaring type. This tells the XAML what control will be implementing this property.

The next parameter is a default value, normally you should put some kind of blank or default value that you want to be displayed.

The final parameter tells Xamarin what to do when the property has been changed. Here we create a static method to handle the transaction.

The following code defines what to do when the property has changed. The first parameter is the object connected to the changed. We will cast this to our custom control.

The next two parameters are the previous value and the new value. In this case, they will be strings. So we can use our newValue to change the text value PersonName in our custom control.

        private static void PersonNameChanged(object bindable, object oldValue, object newValue)
        {
            var b = (MyCustomControl)bindable;
            b.PersonName = (string)newValue;
        }

Updating our XAML

If we go back to our page that implements our custom control, we can now control the value using our new property like so:

image-3You may find that intellisense does some auto-completion for you now. Assuming that everything goes as intended, when you run the application you should now see your intended output in your Xamarin application.

And that’s it! If you have any questions, feel free to drop me a question.

You can download the source for this at: https://github.com/ptdave20/CustomControlsDemo