Search code examples
c#.netxamltriggersmaui

Dotnet Maui DataTrigger not fired on Custom Control Binding


I have created a custom control that is a ValidatableEntry. It has an IsValid public property (bool). I would like to use this property to Enable/Disable a Button. For this, I think I should be able to use a DataTrigger. However it is not working. The Trigger does not fire when the IsValid property changes.

Here is a simplified version that ilustrates the problem. When the entered text is over 5 characters long, the IsValid property changes to true. However, the trigger is not fired and the button remains disabled.

An example repo can be found here: https://github.com/jokogarcia/ExampleForSO

Custom control:

public class ValidatableEntry : ContentView
{
    public Entry Entry { get; set; } = new();
    public int MinimumLength { get; set; }
    public bool IsValid { get; set; }
    public ValidatableEntry()
    {
        this.Entry.TextChanged += OnTextChanged;
        Content = new VerticalStackLayout
        {
            Children = {
                Entry
            }
        };
        
    }

    private void OnTextChanged(object sender, TextChangedEventArgs e)
    {
        Entry entry = sender as Entry;
        IsValid = entry?.Text?.Length> MinimumLength; 
    }
}

XAML:

<VerticalStackLayout
            Spacing="25"
            Padding="30,0"
            VerticalOptions="Center">

            <local:ValidatableEntry
               x:Name="MyEntry"
               MinimumLength="5"/>

            <Button
                x:Name="CounterBtn"
                Text="Click me"
                SemanticProperties.Hint="Counts the number of times you click"
                Clicked="OnCounterClicked"
                IsEnabled="False"
                HorizontalOptions="Center" >
                <Button.Triggers>
                    <DataTrigger TargetType="Button"
                                 Binding="{Binding Source={x:Reference MyEntry},
                                 Path=IsValid}"
                                 Value="True">
                        <Setter Property="IsEnabled" Value="True"></Setter>
                    </DataTrigger>
                </Button.Triggers>
            </Button>

        </VerticalStackLayout>

Solution

  • I found my own answer. I'll share it here for others that come after. What I was missing was to implement INotifyPropertyChanged in my Custom Control. Like this:

    public class ValidatableEntry : ContentView, INotifyPropertyChanged
    {
        [...]
        public bool IsValid
        {
            get { return isValid; }
            set
            {
                isValid = value;
                NotifyPropertyChanged();
            }
        }
        [...]
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    

    EDIT: Actually, this approach later gave me problems when using DataBindings on my control. It is actually not necessary to implement INotifyPropertyChanged because ContentView already implements it. All I needed to do is call OnPropertyChanged() after updating the value.

    So the better and simpler answer would be:

    public class ValidatableEntry : ContentView
    {
        [...]
        public bool IsValid
        {
            get { return isValid; }
            set
            {
                isValid = value;
                OnPropertyChanged();
            }
        }