
May 23, 2022
Dynamic XAML in Xamarin.Forms Applications
When we want to reuse some of our user interface elements in a Xamarin.Forms application, one of the best ways to do it is by using custom controls.
In this Github repository, I created a sample application with a custom control that is a composite of two other controls. I’ll use this example to show you how easy is to implement and use it. This sample application is a standard Xamarin.Forms app with a shared project and the two platform projects–one for iOS and one for Andriod.
In the following screenshot, we can see two instances of the custom control, which is a composite control allowing the user to pick both a date and a time. It exposes bindable properties for the caption and the selected DateTime value.
The visible part of our control is defined in the CustomDateTimePicker.xaml file. In the code-behind file, we define its functionality.
In the XAML file for your custom control, you can use any of the existing Xamarin.Forms controls or other custom controls previously defined.
To create bindable properties, we need a static public property of type BindableProperty, like in the following definition of the Caption property.
public static readonly BindableProperty CaptionProperty = BindableProperty.Create( "Caption", typeof(string), typeof(CustomDateTimePicker), ""); public string Caption { get => (string)GetValue(CaptionProperty); set => SetValue(CaptionProperty, value); }
To avoid a possible collision with an existing property called Caption, in any view-model where the custom control is used, we set an internal name for our control (the “this” name in line 4) and then use that name to create a reference for the binding context holding the bindable property
Regarding the SelectedDateTimeProperty, you can check the OnPropertyChanged code to see how the date and time pickers get their values, and the DatePicker_DateSelected and TimePicker_PropertyChanged events handlers are used for the property getting the value.
To use our new custom control, we will add a tag to MainPage.xaml by using the tag name “CustomDateTimePicker”. We need to add a reference to the namespace where our control is defined (ex: CustomControlSample), and to set the properties as shown in the following screenshot.
Notice that we have two instances of our control in the same view. The Caption property is set to a literal and the SelectedDateTime to a bindable property of the view-model.
And that’s it! We’ve now created a simple custom control which is a composite of two other controls.
Check out the full project here. I hope this was useful for you and please drop a line if you have any questions or comments.
10 thoughts on “Custom Controls in Xamarin.Forms”
Miguel Ángel Martín Hrdez
August 6, 2021 at 11:06 am
Hi!
Nice post, let me ask you.
Do you think that the BindableProperty must be called like the property with the suffix Property? I mean, if the Property is called “Caption”, should the BindableProperty must be called “CaptionProperty”? Or it could be named what ever you want?
Regards!
Rodrigo Juarez
August 6, 2021 at 11:58 am
Hi Miguel! Thanks for reading
The usual convention is to name the BindableProperty with the same name and add the “Property” suffix, but it is up to you if you want to change it because the property is specifically calling the bindable property.
Take a look at lines 23 and 24 in https://github.com/trailheadtechnology/xf-custom-controls/blob/main/CustomControlsSample/CustomControlsSample/CustomDateTimePicker.xaml.cs where the Caption property reference CaptionProperty in the getter and the setter
Dan Meier
August 6, 2021 at 1:32 pm
Hi, Rodrigo. Nice overview! If I wanted to use this custom control in different Xamarin apps, how would I create a library “package” so I could pull it in just as I would a NuGet or other reference?
Also, how do you manage platform-specific behaviors in a separate library “package”? If creating a custom control within an app, one could customize platform-specific behaviors as custom renderers within the Android and iOS projects. Is that possible within a library “package”?
Case in point: Programmatically opening a picker control’s picklist is easy in Android and iOS using the .Focus method. However, the behavior of .Focus in UWP is completely different (yes, some of us still target UWP!), and it’s necessary to create a custom renderer to set the UWP ComboBox control’s .IsDropDownOpen property. This is fairly easy to do within a Xamarin.Forms application project, but how would you do it within a library “package”?
Rodrigo Juarez
August 6, 2021 at 11:04 pm
Hi Dan!
For libraries, you can create a new Xamarin.Forms project and put all your custom controls there and from the shared project create a NuGet package. Any platform-specific code that you include in your custom controls will be packaged and distributed. Then you can consume that package from different projects.
In the near future, I will create a blog post with details and modify the code sample included in this blog post
XFLearner
August 8, 2021 at 10:41 am
Very nice, thanks for sharing it.
Milsugio XSM
November 8, 2021 at 2:35 pm
Why do we need to make the caption property bindable?Couldn’t we just do a public property called Caption with a basic setter ?
Rodrigo Juarez
November 23, 2021 at 10:07 am
Hi!
You will need to use a bindable property so, if you change the value, the UI will update with the new value.
https://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/bindable-properties
Pingback:Control Templates in Xamarin.Forms - Trailhead Technology Partners
Peter
May 2, 2022 at 3:34 pm
Hi Rodrigo,
Thanks for sharing this info.
I looked at the source files, however one thing in the source behind file I don’t understand.
The class “CustomDateTimePicker” is not derived from a base class. I expected it would derived from base class “Grid”, or at least from “BindableObject”. Methods “SetValue(…)” and “GetValue(…)” are defined there.
Is it maybe because the class is “partial”, the other part will be generated by the XML parser and there, that part is derived from “Grid”?
Rodrigo Juarez
May 2, 2022 at 9:46 pm
Yes, you are right, if you look at the generated file from the xaml file (CustomDateTimePicker.xaml.g.cs), you will see that it is a subclass of grid
[global::Xamarin.Forms.Xaml.XamlFilePathAttribute("CustomDateTimePicker.xaml")]
public partial class CustomDateTimePicker : global::Xamarin.Forms.Grid {
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Forms.Build.Tasks.XamlG", "2.0.0.0")]
private global::Xamarin.Forms.Grid @this;