Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xamarin - clearing ListView selection

I am actually working with this piece of code

using System;
using Xamarin.Forms;
using System.Diagnostics;

namespace CryptoUI
{
    public class HomePage : Xamarin.Forms.MasterDetailPage
    {
        public HomePage()
        {
        // Set up the Master, i.e. the Menu
            Label header = new Label
            {
                Text = "MENU",
                Font = Font.SystemFontOfSize(20, FontAttributes.Bold),
                HorizontalOptions = LayoutOptions.Center
            };
        // create an array of the Page names
        string[] myPageNames = {
            "Main",
            "Page 2",
            "Page 3",
        };

        // Create ListView for the Master page.
        ListView listView = new ListView
        {
            ItemsSource = myPageNames,
        };

        // The Master page is actually the Menu page for us
        this.Master = new ContentPage
        {
            Title = "Test",
            Content = new StackLayout
            {
                Children = 
                {
                    header, 
                    listView
                },
            }
        };

        // Define a selected handler for the ListView contained in the Master (ie Menu) Page.
        listView.ItemSelected += (sender, args) =>
        {
            // Set the BindingContext of the detail page.
            this.Detail.BindingContext = args.SelectedItem;

            string currentPage = this.GetType().Name.ToString();

            // This is where you would put your “go to one of the selected pages”
            if(listView.SelectedItem.Equals("Main") && !currentPage.Equals("HomePage")){
                AsyncPush(new HomePage());
            }
            else if(listView.SelectedItem.Equals("Page 2") && !currentPage.Equals("SecondPage")){
                AsyncPush(new SecondPage());
            }
            else if(listView.SelectedItem.Equals("Page 3") && !currentPage.Equals("ThirdPage")){
                AsyncPush(new ThirdPage());
            }               

            // Show the detail page.
            this.IsPresented = false;
        };
            listView.ItemSelected += (senders, e) => {
                if (e.SelectedItem == null) return; // don't do anything if we just de-selected the row
                // do something with e.SelectedItem
                ((ListView)senders).SelectedItem = null; // de-select the row
            };

        // Set up the Detail, i.e the Home or Main page.
        Label myHomeHeader = new Label
        {
            Text = "Home Page",
            HorizontalOptions = LayoutOptions.Center
        };

        string[] homePageItems = { "Alpha", "Beta", "Gamma" };
        ListView myHomeView = new ListView {
            ItemsSource = homePageItems,
        };

        var myHomePage = new ContentPage();

        myHomePage.Content = new StackLayout
        {
            Children = 
            {
                myHomeHeader, 
                myHomeView
            } ,
        };
        this.Detail = myHomePage;
    }

        public async void AsyncPush(Page page)
        {
            await Navigation.PushAsync(page);
        }
    }
}

This code actually shows an easy FlyOut menu, using the Xamarin Forms technologies. I am currently trying to understand how I could easily clear the ListView selection after I have selected which page I want to head to!

I found this piece of code on Xamarin's website for devs (http://developer.xamarin.com/guides/cross-platform/xamarin-forms/working-with/listview/);

listView.ItemSelected += (sender, e) => {
    if (e.SelectedItem == null) return; // don't do anything if we just de-selected the row
    // do something with e.SelectedItem
    ((ListView)sender).SelectedItem = null; // de-select the row
};

But I can't currently figure out how I should integrate it with my code above there :)

like image 319
Guido Magrin Avatar asked Dec 05 '14 00:12

Guido Magrin


5 Answers

I respect all given answers but in an MVVM app you'd better avoid too much code behind. What I usually do is following:

  1. Bind ItemsSource of ListView as usual to an ObservableCollection where T is a CarViewModel in my case

  2. Set SelectionMode="None": This does avoid the selection of SelectedItem on tap

  3. Use EventToCommandBehavior (I use my own implementation; see github.com or use the one from Prism.Forms) to bind ItemTapped event of ListView to my ViewModel command SelectedCarChangedCommand.

  4. In the ViewModel's SelectedCarChangedCommand you'll receive the tabbed item as ItemTappedEventArgs object.

     <ListView
       x:Name="CarsListView"
       ItemsSource="{Binding Cars}"
       SelectionMode="None">
         <ListView.Behaviors>
             <behaviors:EventToCommandBehavior
                 Command="{Binding SelectedCarChangedCommand}"
                 EventName="ItemTapped" />
         </ListView.Behaviors>
    
like image 173
thomasgalliker Avatar answered Nov 05 '22 03:11

thomasgalliker


You're assigning the ItemSelected handler twice, which is a bad idea. All you should have to do is add this line to your existing ItemSelected handler

  ((ListView)sender).SelectedItem = null; 
like image 24
Jason Avatar answered Nov 05 '22 04:11

Jason


ListView.SelectedItem does not have setter (I mean simple Xamarin Android - not Xamarin.Forms). I suggest to use the following code:

private void DeselectEntities()
{
    if (this.listView != null && this.listView.CheckedItemPositions != null)
    {
        this.listView.CheckedItemPositions.Clear();
    }
}
like image 32
Alexander S Avatar answered Nov 05 '22 04:11

Alexander S


I would like to add to Jason's answer because it misses some vital information. When you set the ListView SelectedItem property to null, it will fire off the ItemSelected event again. So if you do not have a null check, it will throw an exception.

This is what it should look like:

void ItemSelected(object sender, EventArgs args)
{
    if (((ListView)sender).SelectedItem == null)
      return;
    //Do stuff here with the SelectedItem ...
    ((ListView)sender).SelectedItem = null;
}
like image 20
Rodolfo De Los Santos Avatar answered Nov 05 '22 03:11

Rodolfo De Los Santos


I had this same problem but the other solutions did not work for me. Since I needed to pass a custom object to the next page I nullified the selected item reference and used the item tapped reference for my custom object.

listView.ItemTapped += async (sender, e) =>{

    await Navigation.PushAsync(new DetailPage(e.Item as CustomObject));
    ((ListView)sender).SelectedItem = null;

};
like image 3
Kelsey Avatar answered Nov 05 '22 03:11

Kelsey