.Net MAUI data binding not carrying through to custom component

Viewed 346

I am having trouble getting data binding to work with custom components.

I have created an IncrementValue property that gets incremented with every button click.

The changes are reflected when binded to a Label. However they do not work when I bind it to a Bindable property in a custom component.

In the example, I have built a custom component called Card which has two bindable properties CardTitle and CardIncrement

Is there something I'm missing as I'm new to MAUI and even Xamarin.

Github link of code snippets below: https://github.com/814k31/DataBindingExample

Card.xaml.cs

namespace DataBindingExample;

public partial class Card : VerticalStackLayout
{
    public static readonly BindableProperty CardTitleProperty = BindableProperty.Create(nameof(CardTitle), typeof(string), typeof(Card), string.Empty);
    public static readonly BindableProperty CardIncrementProperty = BindableProperty.Create(nameof(CardIncrement), typeof(int), typeof(Card), 0);

    public string CardTitle
    {
        get => (string)GetValue(CardTitleProperty);
        set => SetValue(CardTitleProperty, value);
    }

    public int CardIncrement
    {
        get => (int)GetValue(CardIncrementProperty);
        set => SetValue(CardIncrementProperty, value);
    }

    public Card()
    {
        InitializeComponent();

        BindingContext = this;
    }
}

Card.xaml

<?xml version="1.0" encoding="utf-8" ?>
<VerticalStackLayout
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:databindingexample="clr-namespace:DataBindingExample"
    x:DataType="databindingexample:Card"
    x:Class="DataBindingExample.Card"
    Spacing="25"
    Padding="30,0"
    VerticalOptions="Center"
    BackgroundColor="red"
>
    <Label
        Text="{Binding CardTitle}"
        SemanticProperties.HeadingLevel="Level1"
        FontSize="32"
        HorizontalOptions="Center"
    />
    <Label
        Text="{Binding CardIncrement}"
        SemanticProperties.HeadingLevel="Level1"
        FontSize="32"
        HorizontalOptions="Center"
    />
</VerticalStackLayout>

MainPage.xml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="DataBindingExample.MainPage"
    xmlns:DataBindingExample="clr-namespace:DataBindingExample"
    xmlns:ViewModels="clr-namespace:DataBindingExample.ViewModels"
    x:DataType="ViewModels:MainPageViewModel"
>
    <ScrollView>
        <VerticalStackLayout
            Spacing="25"
            Padding="30,0"
            VerticalOptions="Center"
        >
            <Label
                Text="{Binding IncrementedValue}"
                SemanticProperties.HeadingLevel="Level2"
                FontSize="18"
                HorizontalOptions="Center"
            />

            <!-- Why doesnt this work? -->
            <DataBindingExample:Card CardIncrement="{Binding IncrementedValue}" />

            <Button
                x:Name="CounterBtn"
                Text="Click Me"
                SemanticProperties.Hint="Counts the number of times you click"
                Command="{Binding IncrementValueCommand}"
                HorizontalOptions="Center"
            />
        </VerticalStackLayout>
    </ScrollView>
</ContentPage>
1 Answers

When making a custom component (that includes XAML), DO NOT set BindingContext = this;.

REASON: You want the component to use the SAME BindingContext as the page it is placed in. This happens automatically, if you do NOT set a BindingContext in the custom component.

This raises the question: How refer to the card's Properties from its XAML?

By giving the card an x:Name, and making that the "Source" of those bindings:

<VerticalStackLayout
    ...
    x:Name="me"     <-- IMPORTANT! Change name as desired.
    x:Class="DataBindingExample.Card"
>
    ...
    <Label Text={Binding CardIncrement, Source={x:Reference me}}"
    ...
Related