Xamarin.Forms - CommandParameter is always null

lachlanedmistonlachlanedmiston Member ✭✭
edited June 10 in Xamarin.Forms

When a button is clicked I'd like to pass a control's property to the view model using a Command / CommandParameter.

However, when I debug the Command method - Agree() - the CommandParameter I receive is always null. Do I have to set some sort of additional context in the button that calls the Command?

Xaml from view:

<controls:SignaturePad 
            x:Name="signaturePad"/>

<Button
            x:Name="agreeButton"
            Text="I AGREE"
            Command="{Binding AgreeCommand}"
            CommandParameter="{Binding Source={x:Reference signaturePad}, Path=Bytes}"/>

Command definition in ViewModel:

private readonly ReactiveCommand<byte[], Unit> agreeCommand;

public MyViewModel()
{
    this.agreeCommand = ReactiveCommand.CreateFromObservable<byte[], Unit>(
        this.Agree,
        canAgree,
        scheduler);
}

public ReactiveCommand<byte[], Unit> AgreeCommand => this.agreeCommand;

private IObservable<Unit> Agree(byte[] signature)
{
    this.signature = signature;  // Only ever see null here

    // Other system.reactive code...
}

Best Answers

  • JoeMankeJoeManke US ✭✭✭✭✭
    Accepted Answer

    I am very concerned that the bytes member you set in your setter is not referenced in your getter, and also the apparent lack of INotifyPropertyChanged.

  • edited June 30 Accepted Answer

    To provide some closure on this:

    Joe was correct, the CommandParameter on my ReactiveCommand was null because my PCL class member was not being updated with changes from the native side.

    I set up a timer on the native side to poll the UBSignaturePad. If the value changed I manually fired an event to notify the PCL project. Your comment got me thinking "What can I do to make this behave like a properly bound control?".

    Thanks for your time.

Answers

  • JoeMankeJoeManke USMember ✭✭✭✭✭
    edited June 10

    "{Binding Source={x:Reference signaturePad}, Path=Bytes}"

    This suggests that there is a property named Bytes on the SignaturePad class. Does that property actually exist? Is it being set?

  • lachlanedmistonlachlanedmiston Member ✭✭
    edited June 10

    Hi Joe, the property exists in the signaturePad control with the following definition:

    public byte[] Bytes
    {
        get
        {
            if (PollNativeEvent != null)
            {
                var result = PollNativeEvent(this, null);
                return result;
            }
    
            return null; // Changing this to new byte[0] changes the CommandParameter value...
        }
        set => this.bytes = value;
    }
    

    I've now found that when I modify line 11 of the property to return new byte[0] it will change the received CommandParameter to that value.

    Line 11 is only ever called when the view initially loads - after that my renderer assigns a method to extract data from the native control.

    I'm wondering if the value of the CommandParameter is being set on view load and not being updated after? I'll put together a test project to show more context.

  • JoeMankeJoeManke USMember ✭✭✭✭✭
    Accepted Answer

    I am very concerned that the bytes member you set in your setter is not referenced in your getter, and also the apparent lack of INotifyPropertyChanged.

  • lachlanedmistonlachlanedmiston Member ✭✭
    edited June 12

    Hi Joe - I've used a two way binding in that class for another variable.

    The issue with the Bytes property is that the native signature control doesn't raise events every time a stroke is added to the signature. It only raises events when a user adds the first stroke or when the control is cleared. So a binding doesn't update frequently enough to provide up to date data.

    The UberSignature devs didn't anticipate their control being used in a Xamarin renderer. I have a 2.5 month old issue open with the Xamarin.SignaturePad project that prevents me from using that better suited library.

    To get the signature image in bytes I feel like I have to use this approach - triggering an event through the renderer that talks to the native control. I am open to any other suggestions of getting this native data on demand.

    Still working on getting en example project up and running.

  • lachlanedmistonlachlanedmiston Member ✭✭
    edited June 30 Accepted Answer

    To provide some closure on this:

    Joe was correct, the CommandParameter on my ReactiveCommand was null because my PCL class member was not being updated with changes from the native side.

    I set up a timer on the native side to poll the UBSignaturePad. If the value changed I manually fired an event to notify the PCL project. Your comment got me thinking "What can I do to make this behave like a properly bound control?".

    Thanks for your time.

Sign In or Register to comment.