Xamarin Forms:在列表视图中执行搜索时,所选项目被清除

Xamarin Forms: Selected items get cleared when perform search in listview

我已经使用 this 博客从 phone 获取联系人。

现在我正在尝试添加联系人选择。使用开关我已经完成了选择。但是执行搜索操作时,选中的联系人正在清除。

xaml

<Switch
    Toggled="OnToggledEvent"
    HorizontalOptions="EndAndExpand"
    VerticalOptions="CenterAndExpand"/>

xaml.cs

public List<Contact> contactList;
public MainPage(IContactsService contactService)
{
    InitializeComponent();
    contactList = new List<Contact>();
    BindingContext = new ContactsViewModel(contactService);
}

void OnToggledEvent(object sender, EventArgs args)
{
    ViewCell cell = (sender as Xamarin.Forms.Switch).Parent.Parent as ViewCell;
    if (cell.BindingContext is Contact)
    {
        Contact contact = cell.BindingContext as Contact;
        if (contact != null)
        {
            if (contact != null && !contactList.Contains(contact))
            {
                contactList.Add(contact);
            }
            else if (contact != null && contactList.Contains(contact))
            {
                contactList.Remove(contact);
            }
        }
    }
    Debug.WriteLine("contactList:>>" + contactList.Count);
}

ContactsViewModel

public class ContactsViewModel : INotifyPropertyChanged
{
    IContactsService _contactService;
    
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    public string Title => "Contacts";


    string search;
    public string SearchText
    {

        get { return search; }

        set
        {

            if (search != value)
            {
                search = value;
                OnPropertyChanged("SearchText");

                if (string.IsNullOrEmpty(SearchText))
                {
                    FilteredContacts = new ObservableCollection<Contact>(Contacts);

                }

                else
                {

                    FilteredContacts = new ObservableCollection<Contact>(Contacts?.ToList()?.Where(s => !string.IsNullOrEmpty(s.Name) && s.Name.ToLower().Contains(SearchText.ToLower())));

                }
            }

        }

    }

    public ObservableCollection<Contact> Contacts { get; set; }

    ObservableCollection<Contact> filteredContacts;
    public ObservableCollection<Contact> FilteredContacts
    {
        get { return filteredContacts; }

        set
        {

            if (filteredContacts != value)
            {
                filteredContacts = value;
                OnPropertyChanged("FilteredContacts");
            }
        }
    }
    public ContactsViewModel(IContactsService contactService)
    {
        
        _contactService = contactService;
        Contacts = new ObservableCollection<Contact>();
        Xamarin.Forms.BindingBase.EnableCollectionSynchronization(Contacts, null, ObservableCollectionCallback);
        _contactService.OnContactLoaded += OnContactLoaded;
        LoadContacts();
        FilteredContacts = Contacts;
    }


    void ObservableCollectionCallback(IEnumerable collection, object context, Action accessMethod, bool writeAccess)
    {
        // `lock` ensures that only one thread access the collection at a time
        lock (collection)
        {
            accessMethod?.Invoke();
        }
    }

    private void OnContactLoaded(object sender, ContactEventArgs e)
    {
        Contacts.Add(e.Contact);
    }
    async Task LoadContacts()
    {
        try
        {
            await _contactService.RetrieveContactsAsync();
        }
        catch (TaskCanceledException)
        {
            Console.WriteLine("Task was cancelled");
        }
    }
}

我在切换开关时将选定的联系人添加到列表中。如果再次单击开关,我将从列表中删除该联系人。但问题是在搜索联系人时,已经选择的联系人会变得清晰。我尝试使用开关的 IsToggled 属性 来解决这个问题,但没有成功。

我添加了一个示例项目here以供参考。

每次搜索时项目源都会更新,您应该添加一个 属性 内部模型来记录开关的状态并实现 INotifyPropertyChanged。

型号

public class Contact : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public string Name { get; set; }
    public string Image { get; set; }
    public string[] Emails { get; set; }
    public string[] PhoneNumbers { get; set; }

    private bool isToggled;
    public bool IsToggled { 

        get {
            return isToggled;
        } set {
            isToggled = value;
            OnPropertyChanged();
        } 
    }
}

在Xaml

<Switch  IsToggled="{Binding IsToggled} //... >"

修改OnToggledEvent方法如下

void OnToggledEvent(object sender, EventArgs args)
{


    var s = sender as Xamarin.Forms.Switch;
    var model = s.BindingContext as Contact;

    if(model != null)
    {
        if (model.IsToggled && !contactList.Contains(model))
        {
            contactList.Add(model);
        }
        else if (!model.IsToggled && contactList.Contains(model))
        {
            contactList.Remove(model);
        }
    Debug.WriteLine("contactList:>>" + contactList.Count);
    }
}