Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set Xamarin.Forms binding CommandParameter in code behind

I'm trying to set binding on a TapGestureRecognizer in code and I can't figure out the right way to do it. The working xaml looks something like this...

<Grid>
    <Grid.GestureRecognizers>
        <TapGestureRecognizer Command="{Binding LaunchLocationDetailsCommand}" 
                              CommandParameter="{Binding}" />
    </Grid.GestureRecognizers>
</Grid>

And in C#, it looks something like this...

var gridTap = new TapGestureRecognizer();

gridTap.SetBinding(TapGestureRecognizer.CommandProperty, 
                   new Binding("LaunchLocationDetailsCommand"));

gridTap.SetBinding(TapGestureRecognizer.CommandParameterProperty, 
                   new Binding(/* here's where I'm confused */));

var grid = new Grid();
grid.GestureRecognizers.Add(gridTap);

My confusion comes in on the binding of CommandParameterProperty. In xaml, this simply {Binding} with no other parameter. How is this done in code? Passing in new Binding() or this.BindingContext don't seem to work.

like image 953
tarrball Avatar asked Feb 06 '16 05:02

tarrball


2 Answers

The CommandProperty binding is the same as you was doing.

As you are not passing in a path to some property to use, your CommandParameterProperty can't just create an empty Binding as it will throw an exception.

To get around this you need to specify the Source property as Adam has pointed out.

Note, however if the BindingContext you are trying to assign is Null, which I suspect it is in your case, this will still throw an exception.

The Grid in the example below has the BindingContext set to the view model (objGrid.BindingContext = objMyView2).

We are then creating a new binding for our command parameter, with the Source pointing back to our view model (Source = objGrid.BindingContext).

If you run the demo below, you will see a debug message in the Output window indicating a property value from the view model.

        MyView2 objMyView2 = new MyView2();
        objMyView2.SomeProperty1 = "value1";
        objMyView2.SomeProperty2 = "value2";

        objMyView2.LaunchLocationDetailsCommand_WithParameters = new Command<object>((o2)=>
        {
            LaunchingCommands.LaunchLocationDetailsCommand_WithParameters(o2);
        });

        Grid objGrid = new Grid();
        objGrid.BindingContext = objMyView2;
        objGrid.HeightRequest = 200; 
        objGrid.BackgroundColor = Color.Red;

        TapGestureRecognizer objTapGestureRecognizer = new TapGestureRecognizer();
        objTapGestureRecognizer.SetBinding(TapGestureRecognizer.CommandProperty, new Binding("LaunchLocationDetailsCommand_WithParameters"));

        Binding objBinding1 = new Binding()
        {
            Source = objGrid.BindingContext
        };
        objTapGestureRecognizer.SetBinding(TapGestureRecognizer.CommandParameterProperty, objBinding1);
        //
        objGrid.GestureRecognizers.Add(objTapGestureRecognizer);

Supporting classes:-

MyView2:-

public class MyView2
    : ViewModelBase
{
    public string SomeProperty1 { get; set; }
    public string SomeProperty2 { get; set; }

    public ICommand LaunchLocationDetailsCommand_WithParameters { get; set; }
}

LaunchingCommands:-

public static class LaunchingCommands
{
    public static void LaunchLocationDetailsCommand_WithParameters(object pobjObject)
    {
        System.Diagnostics.Debug.WriteLine("SomeProperty1 = " + (pobjObject as MyView2).SomeProperty1);
    }
}

ViewModelBase:-

public abstract class ViewModelBase
    : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void RaisePropertyChanged(string pstrPropertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(pstrPropertyName));
        }
    }

}
like image 64
Pete Avatar answered Nov 02 '22 15:11

Pete


If you have a {Binding} with nothing inside it, it is binding to the binding context and passing that through. Hence you bind it to the default binding context of the page.

When you create a new Binding set the source.

var binding = new Xamarin.Forms.Binding() { Source = this.BindingContext };
like image 37
Adam Avatar answered Nov 02 '22 17:11

Adam