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.
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));
}
}
}
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 };
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With