Dan
Dan

Reputation: 1110

Bind Gesture Recognizers

I am trying to Bind a Gesture Recognizer in Xml so I can handle when an Item is clicked

I tried using this for my XML

<DataTemplate x:Key="TextPostTemplate">
            <ViewCell>
                <StackLayout BackgroundColor="White" Margin="10, 10, 10, 10" Padding="10, 10, 10, 10">
                    <StackLayout Orientation="Horizontal">
                        <Label Text="{Binding Name}" TextColor = "Black" FontSize = "15"/>
                        <Image Source="options_icon.png" HeightRequest="15" HorizontalOptions="EndAndExpand" Margin="0, 0, 10, 0">
                            <Image.GestureRecognizers>
                                <TapGestureRecognizer Tapped="{Binding OptionClick}"/>
                            </Image.GestureRecognizers>
                        </Image>
                    </StackLayout>
                    <Label Text="{Binding Body}" TextColor = "Black"/>
                </StackLayout>
            </ViewCell>
        </DataTemplate>

I try binding it to

 foreach (var post in posts)
        {
      TapGestureRecognizer optionsClick = new TapGestureRecognizer();
            optionsClick.Tapped += (s, e) =>
            {
                ShowPostOptions(page, navigation, post.id, post.user);
            };
}

and...

OptionClick = optionsClick

But I get

.xaml : error : Unable to cast object of type 'Xamarin.Forms.Xaml.ElementNode' to type 'Xamarin.Forms.Xaml.ValueNode'.

Upvotes: 4

Views: 3758

Answers (2)

Martin Zikmund
Martin Zikmund

Reputation: 39072

Your code does not work because you are effectively binding an instance of TapGestureRecognizer to the Tapped event. You cannot data-bind an event and also if you would set it, you would set it to an event handler not an instance of the TapGestureRecognizer itself.

You have two options - either Event Handler or a Command.

Event Handler

Declare the gesture recognizer in XAML as follows:

<TapGestureRecognizer Tapped="TappedHandler" />

And create an event handler called TappedHandler in code-behind of the page:

public void TappedHandler(object sender, EventArgs e)
{
   ShowPostOptions(page, navigation, post.id, post.user);
}

Command

Declare the gesture recognizer in XAML as follows:

<TapGestureRecognizer Command="{Binding TapCommand}" />

And create a command in your view model, that will handle the tap:

private ICommand _tapCommand;

public ICommand TapCommand => _tapCommand ?? 
     ( _tapCommand = new Command( 
          () => ShowPostOptions(page, navigation, post.id, post.user) ) );

Upvotes: 3

TheGeneral
TheGeneral

Reputation: 81493

You are trying to bind an event to a command, then seemingly back again, and its just not going to work

<TapGestureRecognizer Tapped="{Binding OptionClick}"/>

If you have a ICommand in your view model you can do this

<TapGestureRecognizer Command="{Binding TapCommand}" ...

If you have an event ready to go in code behind you can do this

public void OnTapGestureRecognizerTappedEvet(Object sender,EventArgs e) 
{
    // code here
}

<TapGestureRecognizer Tapped="OnTapGestureRecognizerTappedEvet" ...

if you want to do it all in code you can do this

var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.Tapped += (s, e) => {
    // handle the tap
};
image.GestureRecognizers.Add(tapGestureRecognizer);

Adding a Tap Gesture Gesture Recognizer

Upvotes: 2

Related Questions