How to bind a Command to ListView.ItemTapped

ThomasBurkhartThomasBurkhart DEMember ✭✭✭✭

Hi,

I did quite some googling now but did not find an answer. How do I bind a Command to the ItemTapped event of a ListView in Xaml?

Best
Thomas

Best Answers

Answers

  • ThomasBurkhartThomasBurkhart DEMember ✭✭✭✭

    Yes, I've seen this approach at several places, but how to bind to the event?

  • ThomasBurkhartThomasBurkhart DEMember ✭✭✭✭

    Thanks. I will see if your solution is works for me.

  • ThomasBurkhartThomasBurkhart DEMember ✭✭✭✭

    @devnl I tried your solution. Works, but the selected Item isn't unselected.

  • AmerradiAmerradi USMember, University ✭✭
    edited February 2016

    There are two events for use in item selection: ItemTapped (as @SapienDeveloperand mentioned) and ItemSelected. Both can happen when a user taps a cell in the ListView. The difference between them is apparent when a list permits more than just tapping and items can be selected and unselected.

    listView.ItemTapped += async (sender, e) =>
    {
    await DisplayAlert("Tapped", e.Item.ToString() + " was selected.", "OK");
    };
    
    listView.ItemSelected += async (sender, e) =>
    {
    await DisplayAlert("Selected", e.SelectedItem.ToString()+ " was selected.", "OK");
    }
    
  • ThomasBurkhartThomasBurkhart DEMember ✭✭✭✭

    @SapienDeveloper Thanks. I was already fearing that I have to have my own version of a ListView. Pretty weak that the Standard ListView doesn't support this.

  • iLearnXamariniLearnXamarin CHMember ✭✭

    @NMackay said:
    @ThomasBurkhart

    You can do it with Xamarin Forms Behaviours.

    That sample I sent you shows you how. Just set the RelativeContext to the x:Name of your page.

    <ListView Grid.Row="1"
                  ItemsSource="{Binding Orders}"
                  VerticalOptions="Fill"
                  x:Name="ListviewOrder">
          <ListView.ItemTemplate>
            <DataTemplate>
              <ImageCell
                  ImageSource="MyImage"
                  Text="{Binding OrderName}"
                  Detail="{Binding OrderNo}">
                <b:Interaction.Behaviors>
                  <b:BehaviorCollection>
                    <b:EventToCommand CommandNameContext="{b:RelativeContext Details}"
                                      EventName="Tapped"
                                      CommandName="SelectCommand"
                                      CommandParameter="{Binding .}" />
                  </b:BehaviorCollection>
                </b:Interaction.Behaviors>
              </ImageCell>
            </DataTemplate>
          </ListView.ItemTemplate>
        </ListView>
    

    This blog is worth checking out if you don't want another nuget pluggin

    https://anthonysimmon.com/eventtocommand-in-xamarin-forms-apps/

    This one is very nice :+1:
    https://anthonysimmon.com/eventtocommand-in-xamarin-forms-apps/

  • NMackayNMackay GBInsider, University mod

    @iLearnXamarin

    I use this one at the moment

    https://www.nuget.org/packages/Behaviors.Forms/

    One nice things is it doesn't need to reference the platform specific libraries to be initialized and it's well documented.
    http://www.davidbritch.com/

  • iLearnXamariniLearnXamarin CHMember ✭✭

    Thanks.

    Downloads: 689. I might wait a bit :-).

    For the moment I'm happy with:
    https://anthonysimmon.com/eventtocommand-in-xamarin-forms-apps/

    Cheers!

  • ErickMendoncaErickMendonca BRMember

    I'm using this workaround:

    I bind ListView.SelectedItem to something on my ViewModel. When it changes, I call my method :smile:

  • jesulink2514jesulink2514 USUniversity ✭✭
    edited September 2016

    Great, I just changed

             if (e.Item != null && this.ItemClickCommand != null && this.ItemClickCommand.CanExecute(e))
    

    for this

             if (e.Item != null && this.ItemClickCommand != null && this.ItemClickCommand.CanExecute(e.Item))
    

    @SapienDeveloper said:
    here is a simple listview with an added command binding for tapped items. should unselect the item once its tapped.

    `public class ListView : Xamarin.Forms.ListView
    {
    public static BindableProperty ItemClickCommandProperty = BindableProperty.Create<ListView, ICommand>(x => x.ItemClickCommand, null);

        public ListView()
        {
            this.ItemTapped += this.OnItemTapped;
        }
    
    
        public ICommand ItemClickCommand
        {
            get { return (ICommand)this.GetValue(ItemClickCommandProperty); }
            set { this.SetValue(ItemClickCommandProperty, value); }
        }
    
        private void OnItemTapped(object sender, ItemTappedEventArgs e)
        {
            if (e.Item != null && this.ItemClickCommand != null && this.ItemClickCommand.CanExecute(e))
            {
                this.ItemClickCommand.Execute(e.Item);
                this.SelectedItem = null;
            }
        }
    }`
    
  • JulienRosenJulienRosen CAMember ✭✭✭✭
    edited September 2016

    I use Fody.PropertyChanged, bind against SelectedItem, and just monitor for selected item changes using fody's OnSelectedItemChanged method.

    I also have a code behind event on the listbox that deselects the selected item immediately.

  • FaisalGFaisalG GBMember ✭✭

    @SapienDeveloper

    Elegant, but my question is - how do you apply it?

    In my XAML page I have this:

        <controls:CommandListView ItemsSource="{Binding Skills}" x:Name="skillsListView" 
    SelectedItem="{Binding MySelectedItem, Mode=TwoWay}"
    ItemClickCommand="{Binding SelectedItemExecuteCommand}">
          <ListView.ItemTemplate>
            <DataTemplate>
              <ViewCell>
                <Label Text="{Binding Name}"></Label>
              </ViewCell>
            </DataTemplate>
          </ListView.ItemTemplate>
        </controls:CommandListView>
    

    And in the VM, the bound Command where (I guess) I would retrieve the Item fired in the OnItemTapped event:

            public Command SelectedItemExecuteCommand
            {
                get
                {
                    return new Command(() =>
                    {
                // How do you capture the ItemTappedEventArgs arg?
                    });
                }
            }
    

    How would you access the ItemTappedEventArgs variable that was handled by the OnItemTapped handler?

  • SapienDeveloperSapienDeveloper USMember ✭✭

    @FaisalG
    You have done all the right steps.
    To capture the actual item being tapped on all you have to do is introduce a parameter to your Command.

    public Command SelectedItemExecuteCommand
        {
            get
            {
                return new Command<{parameterType}>((p) =>
                {
                    //specify a parameter type like above 
                    // and 'p' will be the item which was tapped
                });
            }
        }
    
  • FaisalGFaisalG GBMember ✭✭

    Great! Thank you @SapienDeveloper

  • RayQuRayQu NZMember

    @devnl

    Hi Steven,
    Your code works well but deselect the list view. At the very last line, you set the SelectedItem = null, are you trying to deselect the row? But it didn't work for me. Any idea?

    Cheers.

    @devnl said:
    Since there's no Command property to bind to we do it this way:

    <ListView ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" HasUnevenRows="True" CachingStrategy="RecycleElement" SeparatorVisibility="None">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <Label Grid.Row="0" TextColor="#000000" Text="Test" />
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    

    And in the ViewModel behind that:

    public Item SelectedItem
    {
        get
        {
            return _selectedItem; 
        }
        set
        {
            _selectedItem = value;
    
            if (_selectedItem == null)
                return;
                
            SomeCommand.Execute(_selectedItem);
    
            SelectedItem = null;
        }
    }
    
  • Ben.2646Ben.2646 USMember ✭✭

    @RayQu , SelectedItem is set to null because if you dont, if you click on the selected item the setter doesn't fire.

  • 3pa23pa2 USMember ✭✭

    And what is the difference between using listview.tapped + = ..... to use command to handle the same event?

  • JulienRosenJulienRosen CAMember ✭✭✭✭

    @3pa2 tapped gives you a code behind method
    command gives you the ability to bind to a method in your BindingContext

  • 3pa23pa2 USMember ✭✭

    @JulienRosen said:
    @3pa2 tapped gives you a code behind method
    command gives you the ability to bind to a method in your BindingContext

    ohhh lol
    I understand well hehe

  • CiroORICCiroORIC BRMember ✭✭

    Another approach using XAML Attached Property (forget XAML code behind): michaelridland.com/xamarin/xaml-attached-properties-tricks-in-xamarin-forms/#comment-2141

    I hope it help you!

    Regards

  • RubitoRubito USMember

    @CiroORIC said:
    Another approach using XAML Attached Property (forget XAML code behind): michaelridland.com/xamarin/xaml-attached-properties-tricks-in-xamarin-forms/#comment-2141

    I hope it help you!

    Regards

    Awesome, this solution is actually so good, that I can get rid of many helper behaviors that only added noise in my XAML.

  • SakisAthSakisAth DEMember ✭✭

    @SapienDeveloper Thank you very much for your solution. It solved my problem and works nice.
    But I have a question with the implementation of :

    public static BindableProperty ItemClickCommandProperty = 
                BindableProperty.Create<ListView, ICommand>(x => x.ItemClickCommand, null);
    

    It says that generic versions of Create are deprecated and will be removed soon. Is there another way to use it?

  • SapienDeveloperSapienDeveloper USMember ✭✭
    edited June 2017

    @SakisAth
    Use the format below. make sure to add your Custom list view in the Declaring Type parameter.

    public static readonly BindableProperty ItemClickCommandProperty = BindableProperty.Create("ItemClickCommand", typeof(object), typeof({Custom List View Here}), null, BindingMode.Default);

Sign In or Register to comment.