xamarinbindableproperty

Xamarin - Binding to a Property of a child control inside a custom control


I am working on a Xamarin App. I am making a custom control with a Label control, a DatePicker control and an Entry control. I had to create quite a few BindableProperties for the Date Control in the Custom Control such as MaximumDate, MinimumDate Property among many other properties. As far as I understand, the reason I have to create these BindableProperty members in my Custom control are because I have no access to the properties of the child controls when the custom control is used on a view. Is there a way to access the properties of the child control that is embedded in a custom control? I could save a lot of lines of code defining the BindableProperties and their CLR properties and other things.

Here is my Custom control XAML (I have removed all the elements except for a Label element in the posted code to make the code more readable and for brevity.

<StackLayout xmlns="http://xamarin.com/schemas/2014/forms" 
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="DPSReminders.Controls.CustomLabel"
         xmlns:controls="clr-namespace:DPSReminders.Controls"
         xmlns:sfLayout="clr-namespace:Syncfusion.XForms.TextInputLayout;assembly=Syncfusion.Core.XForms"
         xmlns:sfPicker="clr-namespace:Syncfusion.XForms.Pickers;assembly=Syncfusion.SfPicker.XForms"
         xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
         xmlns:fai="clr-namespace:FontAwesome">
<StackLayout.Resources>
    <ResourceDictionary>
    </ResourceDictionary>
</StackLayout.Resources>
<StackLayout Orientation="Horizontal" Margin="10">
    <Label x:Name="myLabel" 
            Text=""
            FontFamily="FASolid"
            VerticalOptions="Center"
            HorizontalOptions="Start"
            Margin="10">
    </Label>
</StackLayout>

The code behind file:

public class CustomLabel : StackLayout
{
public static readonly BindableProperty LabelTextProperty =
BindableProperty.Create(nameof(LabelText), typeof(string), typeof(CustomLabel),
    defaultBindingMode: BindingMode.TwoWay,
    propertyChanged: LabelTextPropertyChanged);

public string LabelText
{
    get => GetValue(LabelTextProperty)?.ToString();
    set => SetValue(LabelTextProperty, value);
}

private static void LabelTextPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
    var control = bindable as CustomLabel;
    control.myLabel.Text = newValue?.ToString();
}

public CustomLabel()
{
    InitializeComponent();
}
}

Here is the page where I am trying to use the custom control.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="DPSReminders.Views.DateTimeTest"
         xmlns:fai="clr-namespace:FontAwesome"
         xmlns:vm="clr-namespace:DPSReminders.ViewModels"
         xmlns:controls="clr-namespace:DPSReminders.Controls"
         xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
         >
    <controls:CustomLabel LabelText = "{Binding MyLabelText}"/>
</ContentPage>

I am wondering if I could do a line like this in my label, that would make my life much easier.

    <controls:CustomLabel:myLabel.Text = "{Binding MyLabelText}"/>

Then, I can remove all the code creating the BindableProperties and the supporting CLR properties etc. when a built-in bindable property for the same purpose is already available in the child control. Is this something we can do?


Solution

  • Try using template instead.

    Xamarin.Forms control templates enable you to define the visual structure of ContentView derived custom controls, and ContentPage derived pages. Control templates separate the user interface (UI) for a custom control, or page, from the logic that implements the control or page. Additional content can also be inserted into the templated custom control, or templated page, at a pre-defined location.

    Doc link: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/templates/control-template