Ch1h0
Ch1h0

Reputation: 43

Search handler with data binding from viewModel in .NET MAUI

I have a .NET MAUI mobile app and I'm trying to implement a SearchHandler with data binding from ViewModel.

I have the code below, but I'm getting "No property, BindableProperty, or event found for "Clients", or mismatching type between value and property" error.

In ClientPage.xaml

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vm="clr-namespace:Realizer.ViewModels"
             xmlns:sh="clr-namespace:Realizer.Resources.SearchHandlers"
             xmlns:models="clr-namespace:Realizer.Models"
             x:DataType="vm:ClientsViewModel"
             x:Class="Realizer.Pages.ClientsPage"
             Title="Clients">
    
    <Shell.SearchHandler>
        <sh:ClientSearchHander ShowsResults="True"
                               Clients="{Binding Clients}"
                               DisplayMemberName="Name">
            
        </sh:ClientSearchHander>
    </Shell.SearchHandler>

In ClientSearchHandler.cs

namespace Realizer.Resources.SearchHandlers
{
    public class ClientSearchHandler : SearchHandler
    {
        //public static readonly BindableProperty Clients;
        public ObservableCollection<Client> Clients { get; set; }
        protected  override void OnQueryChanged(string oldValue, string newValue)
        {
            base.OnQueryChanged(oldValue, newValue);
            if(string.IsNullOrWhiteSpace(newValue))
            {
                ItemsSource = null;
            }
            else
            {
                ItemsSource = Clients.Where(x => x.Name.Contains(newValue)).ToList();
            }
        }

        protected override void OnItemSelected(object item)
        {
            base.OnItemSelected(item);
        }
    }
}

In ClientsViewModel.cs

public partial class ClientsViewModel : ObservableObject
{
        [ObservableProperty]
        private ObservableCollection<Client> _clients = new();
       
        public async Task LoadClientsAsync()
        {
           var clients = await _context.GetAllAsync<Client>();

           if (clients is not null && clients.Any())//if we have at least one client
           {
               Clients ??= new ObservableCollection<Client>(); //if null, initialize

               foreach (var client in clients)
               {
                   Clients.Add(client);
               }
           }
         }
}

I saw someone asking the same question here and tried to make Clients in ClientSearchHandler.cs BindableProperty as I have commented. But it conflicted when I set Client.Where(...) saying "'BindableProperty' does not contain a definition for 'Where'."

Upvotes: 0

Views: 474

Answers (1)

Liyun Zhang - MSFT
Liyun Zhang - MSFT

Reputation: 14444

As Jason said, you can create the BindableProperty for the Clients property. And I have tested it and make it work.

The ClientSearchHandler.cs:

public class ClientSearchHandler : SearchHandler
    {
        public static readonly BindableProperty ClientsProperty
            = BindableProperty.Create("Clients", typeof(ObservableCollection<Client>), typeof(ClientSearchHandler), null);
        public ObservableCollection<Client> Clients
        {
            get=>(ObservableCollection<Client>)GetValue(ClientsProperty);
            set=>SetValue(ClientsProperty,value);
        }
        protected override void OnQueryChanged(string oldValue, string newValue)
        {
            base.OnQueryChanged(oldValue, newValue);
            if (string.IsNullOrWhiteSpace(newValue))
            {
                ItemsSource = null;
            }
            else
            {
                ItemsSource = Clients.Where(x => x.Name.Contains(newValue)).ToList();
            }
        }
       
        protected override void OnItemSelected(object item)
        {
            base.OnItemSelected(item);
        }
    }

And the result image:

enter image description here

If you have added the code about the bindableproperty, you can try to clean and rebuild the project to use it.

Upvotes: 1

Related Questions