Execute a Command in the PropertyChangedDelegate of another BindableProperty in a user control

I'm a little at loss (and sligtly going nuts) with a problem in a user control.

I created a custom control that simulate dropdown-like behaviour. (A ContentView with a Label and a popup with a ListView. Tapping the label opens the popup)
It has bindable properties like Items, SelectedText, SelectValue, and a Command-property SelectedCommand.
The Command gets executed if the user selects one of the items by tapping on it. This all works fine. The label gets updated and the SelectedCommand executed notifying the viewmodel that the selection is changed.

But now I try to execute the SelectedCommand when the list of Items only contains 1 item.
If there is only 1 item, the the label is updated and the Command should be executed as if the user chose this one item.
Like this:

public static readonly BindableProperty ItemsProperty = BindableProperty.Create(nameof(Items), typeof(List<DropdownItem>), typeof(DropdownView), null, BindingMode.TwoWay, null, (bindable, oldValue, newValue) =>
{
    var ddl = (DropdownView)bindable;
    ddl.ItemsChanged();
});

private void ItemsChanged()
{
    if (Items.Count == 1)
    {
        SelectedText = Items[0].Text;
        SelectedValue = Items[0].Value;
        SelectedCommand?.Execute(SelectedValue);
    }
}

SelectedText and SelectValue are filled with the correct values, but the value of SelectedCommand is always null and thus the command is not executed.
The SelectedCommand property is nothing special, just de standard markup:

        public static readonly BindableProperty SelectedCommandProperty =
            BindableProperty.Create(nameof(SelectedCommand), typeof(ICommand), typeof(DropdownView), null);

        public ICommand SelectedCommand
        {
            get => (ICommand)GetValue(SelectedCommandProperty);
            set => SetValue(SelectedCommandProperty, value);
        }

I spent hours trying to solve this. For testing I even added an PropertyChangedDelegate handler on de SelectedCommand property to verify if it gets a value, and it does, before ItemsChanged() is called, so it should have a value then.
Why is the SelectedCommand property null??
Is it possible to execute a Command from within a PropertyChangedDelegate?
Am I doing this wrong? If so, what is the correct way to do this?

Answers

  • KeesAlderliestenKeesAlderliesten NLMember ✭✭

    I finally found it. Reading the docs on BindableProperties this line triggert the solution:
    'Note that all BindableProperty instances must be created on the UI thread'.
    https://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/bindable-properties
    So I wrapped this 3 lines in a BeginInvokeOnMainThread:

    if (Items.Count == 1)
    {
        Device.BeginInvokeOnMainThread(() =>
        {
            SelectedText = Items[0].Text;
            SelectedValue = Items[0].Value;
            SelectedCommand?.Execute(SelectedValue);
        });
    }
    

    And now it works!

Sign In or Register to comment.