Redduke
Redduke

Reputation: 39

I cannot invoke command while clicking on listview items Xamarin forms

I encountered problem in which, In a List view I can invoke the first element, and only first. I also want to trigger my command when the row Cell is clicked anywhere inside, but my command triggers only when the label clicked and only in the first cell. Any ideas to resolve my problem? Thanks a lot

<StackLayout Grid.Row="3">
  <ListView x:Name="meetingList" ItemsSource="{Binding MeetingDetails}" RowHeight = "100">
    <ListView.ItemTemplate >
      <DataTemplate>
        <ViewCell>
          <StackLayout BackgroundColor="Red">
            <ContentView>
              <Grid>
                <Grid.RowDefinitions>
                  <RowDefinition Height="40"/>
                  <RowDefinition Height="40"/>
                  <RowDefinition Height="40"/>
                  <RowDefinition Height="40"/>
                </Grid.RowDefinitions>
                <StackLayout  Margin="10,0" BackgroundColor="red" Padding="15,10,15,10" HeightRequest="100" Orientation="Vertical" HorizontalOptions="StartAndExpand" >
                  <Label x:Name="Label_Name" Text="{Binding Name}" />
                  <Label>
                    <Label.FormattedText>
                      <FormattedString>
                        <Span Text="{Binding DateOfStart}" FontAttributes="Bold"/>
                        <Span Text="-"></Span>
                        <Span Text="{Binding DateOfEnd}" FontAttributes="Bold" />
                      </FormattedString>
                    </Label.FormattedText>
                    <Label.GestureRecognizers>
                      <TapGestureRecognizer Command="{Binding BindingContext.ShowDetailsCommand, Source={x:Reference Name=calendarPage}}"></TapGestureRecognizer>
                    </Label.GestureRecognizers>
                  </Label>
                </StackLayout>
              </Grid>
            </ContentView>
            <StackLayout.GestureRecognizers>
              <TapGestureRecognizer Command="{Binding BindingContext.ShowDetailsCommand, Source={x:Reference Name=meetingList}}"></TapGestureRecognizer>
            </StackLayout.GestureRecognizers>
          </StackLayout>
        </ViewCell>
      </DataTemplate>
    </ListView.ItemTemplate>
  </ListView>
</StackLayout>

enter image description here

Upvotes: 1

Views: 261

Answers (2)

Leon Lu
Leon Lu

Reputation: 9274

I changed your layout like following code.

    <StackLayout Grid.Row="3">
    <ListView x:Name="meetingList" ItemsSource="{Binding MeetingDetails}" RowHeight = "100">
        <ListView.ItemTemplate >
            <DataTemplate>
                <ViewCell>
                    <StackLayout BackgroundColor="Red">

                        <StackLayout.GestureRecognizers>
                            <TapGestureRecognizer Command="{Binding BindingContext.ShowDetailsCommand, Source={x:Reference Name=meetingList}}" CommandParameter="{Binding .}"></TapGestureRecognizer>
                        </StackLayout.GestureRecognizers>

                        <ContentView>
                            <Grid>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="40"/>
                                    <RowDefinition Height="40"/>
                                    <RowDefinition Height="40"/>
                                    <RowDefinition Height="40"/>
                                </Grid.RowDefinitions>
                                <StackLayout  Margin="10,0" BackgroundColor="red" Padding="15,10,15,10" HeightRequest="100" Orientation="Vertical" HorizontalOptions="StartAndExpand" >
                                    <Label x:Name="Label_Name" Text="{Binding Name}" />
                                    <Label>
                                        <Label.FormattedText>
                                            <FormattedString>
                                                <Span Text="{Binding DateOfStart}" FontAttributes="Bold"/>
                                                <Span Text="-"></Span>
                                                <Span Text="{Binding DateOfEnd}" FontAttributes="Bold" />
                                            </FormattedString>
                                        </Label.FormattedText>
                                        <Label.GestureRecognizers>
                                            <TapGestureRecognizer Command="{Binding BindingContext.ShowDetailsCommand}"></TapGestureRecognizer>
                                        </Label.GestureRecognizers>
                                    </Label>
                                </StackLayout>
                            </Grid>
                        </ContentView>

                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</StackLayout>

Here is running GIF. enter image description here

I do not know what is your mean about <TapGestureRecognizer Command="{Binding BindingContext.ShowDetailsCommand, Source={x:Reference Name=calendarPage}}"></TapGestureRecognizer>

If you want to get the click item's model. You can use CommandParameter like this code.<TapGestureRecognizer Command="{Binding BindingContext.ShowDetailsCommand, Source={x:Reference Name=meetingList}}" CommandParameter="{Binding .}"></TapGestureRecognizer>

In the ViewModel, you can get the click model.

  ShowDetailsCommand = new Command<MyModel>((key)=> {

            var myStr = key;

            Console.WriteLine("Name: " + myStr.Name+" "+myStr.DateOfStart+" "+myStr.DateOfEnd);

        });

Here is my demo. https://github.com/851265601/ListviewCLickCommand

Upvotes: 1

Joe H
Joe H

Reputation: 614

The problem is that:

<StackLayout.GestureRecognizers>
    <TapGestureRecognizer Command="{Binding BindingContext.ShowDetailsCommand, Source={x:Reference Name=meetingList}}"></TapGestureRecognizer>
</StackLayout.GestureRecognizers>

Captures the Tap and so the internal TapGestureRecognizer is not doing anything because the Tap is already captured. The best way would be to use an EventToCommandBehavior

https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/behaviors/reusable/event-to-command-behavior

And capture the ItemSelected event. Something along these lines

<ListView.Behaviors>
    <prism:EventToCommandBehavior EventName="ItemSelected"
                          Command="{Binding SymbolClickedCommand}"
                          EventArgsParameterPath="SelectedItem" />
</ListView.Behaviors>

The above is using Prism which provides a EventToCommandBehavior but it the same idea using the one defined in the link

I have a general rule in Xamarin, if I think I need to use TapGestureRecognizer then I am doing something wrong. But that is probably opinion

Upvotes: 1

Related Questions