Search Filter in Xamarin Listview

2.2k Views Asked by At

I'm trying to create a program in which I can enter the data and delete the data. I did all the other parts except the search part. I couldn't make a working search box. My codes are below :

TalepInfoPage.xaml :

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:SqLiteXamarinCrud"
             x:Class="SqLiteXamarinCrud.Views.TalepInfoPage">

    <ContentPage.BindingContext>

        <local:TalepInfoViewModel/>
    </ContentPage.BindingContext>

    <ContentPage.ToolbarItems>

        <ToolbarItem Text="Ekle" Clicked="ToolbarItem_Clicked"/>

    </ContentPage.ToolbarItems>




    <ContentPage.Content>
        <StackLayout>
            <SearchBar x:Name="MainSearchBar" Placeholder="Arama" SearchButtonPressed="SearchBar_SearchButtonPressed"></SearchBar>
            <StackLayout>



                <ListView ItemsSource="{Binding ItemList} "
                      HasUnevenRows="True"
                      SeparatorColor="Blue"
                      SeparatorVisibility="None"
                      IsPullToRefreshEnabled="True"
                      RefreshControlColor="DarkRed"
                      
                          >
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <ViewCell>
                                <ViewCell.ContextActions>
                                    <MenuItem Text="Favori"></MenuItem>
                                    <MenuItem Text="Sil"></MenuItem>
                                </ViewCell.ContextActions>
                                
                                <Grid Padding="10">
                                    <Frame CornerRadius="10" HasShadow="True">
                                        <StackLayout Orientation="Horizontal">
                                            <Image Source="{Binding ImageUrl}" WidthRequest="100" HeightRequest="100"></Image>
                                            <StackLayout VerticalOptions="Center">

                                                <Label VerticalOptions="Center" Text="{Binding ProductName}" FontSize="Large"></Label>
                                                <Label VerticalOptions="Center" Text="{Binding Aciklama}" FontSize="Medium"></Label>

                                            </StackLayout>

                                            <StackLayout VerticalOptions="Center" HorizontalOptions="EndAndExpand">

                                                <Image Source="edit.png"
                                                   WidthRequest="30"
                                                   HeightRequest="30">

                                                    <Image.GestureRecognizers>
                                                        <TapGestureRecognizer 
                                                        Tapped="TapGestureRecognizer_Tapped"
                                                        CommandParameter="{Binding ProductId}"
                                                        
                                                        />

                                                    </Image.GestureRecognizers>

                                                </Image>
                                                <Image Source="trash.png"
                                                   WidthRequest="30"
                                                   HeightRequest="30">

                                                    <Image.GestureRecognizers>
                                                        <TapGestureRecognizer
                                                   Tapped="TapGestureRecognizer_Tapped_1"
                                                    CommandParameter="{Binding ProductId}"/>

                                                    </Image.GestureRecognizers>

                                                </Image>

                                            </StackLayout>

                                        </StackLayout>

                                    </Frame>
                                </Grid>

                            </ViewCell>

                        </DataTemplate>
                    </ListView.ItemTemplate>

                    <ListView.Header>



                        <StackLayout Orientation="Horizontal" HorizontalOptions="Center">
                            <Label Text="Ürün Bilgisi" FontSize="Large" TextColor="Black"></Label>

                        </StackLayout>

                    </ListView.Header>


                    <ListView.Footer>
                        <StackLayout Orientation="Horizontal" HorizontalOptions="Center">
                            <Button Text="Daha Fazla" FontSize="Large" TextColor="Black"></Button>

                        </StackLayout>

                    </ListView.Footer>
                </ListView>
            </StackLayout>

        </StackLayout>
    </ContentPage.Content>
</ContentPage>

TalepInfoPage.xaml.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace SqLiteXamarinCrud.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class TalepInfoPage : ContentPage
    {
        public TalepInfoPage()
        {
            InitializeComponent();

        }

        private void ToolbarItem_Clicked(object sender, EventArgs e)
        {

            Navigation.PushAsync(new AddOrEditTalepPage());

        }

        private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
        {

            TappedEventArgs tappedEventArgs = (TappedEventArgs)e;
            TalepInfo talepInfo = ((TalepInfoViewModel)BindingContext).ItemList.
                Where(prod=> prod.ProductId==(int)tappedEventArgs.Parameter).FirstOrDefault();

            Navigation.PushAsync(new AddOrEditTalepPage(talepInfo));
        }

        private void TapGestureRecognizer_Tapped_1(object sender, EventArgs e)
        {

            TappedEventArgs tappedEventArgs = (TappedEventArgs)e;
            TalepInfo talepInfo = ((TalepInfoViewModel)BindingContext).ItemList.
                Where(prod => prod.ProductId == (int)tappedEventArgs.Parameter).FirstOrDefault();

            ((TalepInfoViewModel)BindingContext).ItemList.Remove(talepInfo);

        }


    }
    }

TalepInfoViewModel.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using Xamarin.Forms;

namespace SqLiteXamarinCrud
{
    public class TalepInfoViewModel
    {

         public ObservableCollection<TalepInfo> ItemList { get; set; }
        public TalepInfoViewModel()

        {
            ItemList= new ObservableCollection<TalepInfo> ();
            ItemList.Add(new TalepInfo() { ProductId = 1, ProductName = "Deneme1", Aciklama = "Denemeler1", ImageUrl = "pc.png" });
            ItemList.Add(new TalepInfo() { ProductId = 2, ProductName = "Deneme2", Aciklama = "Denemeler2", ImageUrl = "pc.png" });
            ItemList.Add(new TalepInfo() { ProductId = 3, ProductName = "Deneme3", Aciklama = "Denemeler3", ImageUrl = "pc.png" });
            ItemList.Add(new TalepInfo() { ProductId = 4, ProductName = "Deneme4", Aciklama = "Denemeler4", ImageUrl = "pc.png" });
            ItemList.Add(new TalepInfo() { ProductId = 5, ProductName = "Deneme5", Aciklama = "Denemeler5", ImageUrl = "pc.png" });


            MessagingCenter.Subscribe<AddOrEditTalepPage, TalepInfo>(this, "AddOrEditTalep",(page,talep)=> {
            if(talep.ProductId == 0) 
            {

                    talep.ProductId = ItemList.Count + 1;
                    ItemList.Add(talep);

            }
                else 
                {
                    TalepInfo talepInfoForEdit = ItemList.
                    Where(prod => prod.ProductId == talep.ProductId).FirstOrDefault();

                    int newIndex = ItemList.IndexOf(talepInfoForEdit);
                    ItemList.Remove(talepInfoForEdit);

                    ItemList.Add(talep);

                    int oldIndex = ItemList.IndexOf(talep);
                    ItemList.Move(oldIndex, newIndex);
                }

            });
        }


       
    }
}

TalepInfo.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace SqLiteXamarinCrud
{
    public class TalepInfo
    {

        public int ProductId { get; set; }
        public string ProductName { get; set; }
        public string Aciklama { get; set; }
        public string ImageUrl { get; set; }

        internal static object Where(Func<object, bool> p)
        {
            throw new NotImplementedException();
        }
    }
}
1

There are 1 best solutions below

1
On

Definitely you can! This can be achieved through performing a search with event handlers or using a viewmodel.Please see my code snippets for your reference!

1.Event handlers:

Code in Xaml:

  <StackLayout>
    <SearchBar x:Name="CountriesSearchBar"  
             TextChanged="Handle_SearchButtonPressed"/>
    <ListView x:Name="CountrySearchList" Footer=""/>
  </StackLayout>

Code behind:

    List<string> countries = new List<string>
    {
        "Dominican Republic" , "United States" , "Spain" , "Costa Rica"
    };

    void Handle_SearchButtonPressed(object sender, System.EventArgs e)
    {
        var countriesSearched = countries.Where(c => c.Contains(CountriesSearchBar.Text));
        CountrySearchList.ItemsSource = countriesSearched;
    }

2.Via ViewModel:

SearchPage.xaml

<ContentPage.BindingContext>
    <appsearchbar:SearchPageViewModel />
</ContentPage.BindingContext>
<StackLayout>
    <SearchBar x:Name="searchBar"
               HorizontalOptions="Fill"
               VerticalOptions="CenterAndExpand"
               Placeholder="Search fruits..."
               SearchCommand="{Binding PerformSearch}" 
               SearchCommandParameter="{Binding Text, Source={x:Reference searchBar}}"/>
    <Label Text="Enter a search term and press enter or click the magnifying glass to perform a search."
           HorizontalOptions="Fill"
           VerticalOptions="CenterAndExpand" />
    <ListView x:Name="searchResults"
              HorizontalOptions="Fill"
              VerticalOptions="CenterAndExpand"
              ItemsSource="{Binding SearchResults}"/>
</StackLayout>

SearchPageViewModel.cs

 public class SearchPageViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public ICommand PerformSearch => new Command<string>((string query) =>
    {
        SearchResults = DataService.GetSearchResults(query);
    });

    List<string> searchResults = DataService.Fruits;
    public List<string> SearchResults
    {
        get
        {
            return searchResults;
        }
        set
        {
            searchResults = value;
            NotifyPropertyChanged();
        }
    }
}