Xamarin.Forms搜索结果无法实时更新,仅热重载生效问题求助
嘿,我看了你的代码,发现几个关键问题导致搜索列表没法实时更新,咱们一个个来解决:
你用了List<Herd>来存搜索结果,但List<T>本身不会触发集合变更通知——当你调用Add添加匹配项时,UI根本不知道集合已经变了,只有热重载时UI重新绑定数据上下文,才会读到最新的列表内容。
解决方法很简单:把HerdSearchResults换成ObservableCollection<Herd>,它会自动在添加/移除元素时通知UI更新。
你的SearchChrOrAddress方法里,循环只是把AllHerds的最后一个元素赋值给herdMatch,然后只检查这一个元素是否匹配——这根本不是遍历所有元素做搜索啊!而且每次搜索都没清空之前的结果,会导致匹配项不断累加。
正确的逻辑应该是:先清空旧结果,再遍历所有牧群,把符合条件的元素加进去。
你在SearchInput的setter里调用了RaisePropertyChanged(nameof(HerdSearchResults)),这完全没必要——搜索逻辑是通过命令触发的,而且用ObservableCollection的话,集合内部的变更会自动通知UI,这个手动通知反而可能干扰。
修改后的ViewModel代码
using System.Collections.ObjectModel; // 记得引入这个命名空间 public class CreateHerdPageViewModel : ViewModelBase { private IHerdService herdService; private string searchInput; public string SearchInput { get => searchInput; set => SetProperty(ref searchInput, value); // 移除多余的RaisePropertyChanged } // 把List替换成ObservableCollection private ObservableCollection<Herd> herdSearchResults; public ObservableCollection<Herd> HerdSearchResults { get => herdSearchResults; set => SetProperty(ref herdSearchResults, value); } private List<Herd> allHerds; public List<Herd> AllHerds { get => allHerds; set => SetProperty(ref allHerds, value); } public DelegateCommand SearchChrOrAddressCommand { get; set; } public CreateHerdPageViewModel(INavigationService navigationService, IHerdService herdService) : base(navigationService) { this.herdService = herdService; SearchChrOrAddressCommand = new DelegateCommand(SearchChrOrAddress); } private void SearchChrOrAddress() { // 先清空之前的搜索结果 HerdSearchResults.Clear(); // 搜索输入为空时直接返回,也可以改成显示全部牧群,看你的需求 if (string.IsNullOrWhiteSpace(SearchInput)) return; // 遍历所有牧群,检查匹配条件 foreach (var herd in AllHerds) { // 一定要做空值检查,避免空引用异常 if (herd?.ChrAddress?.Area != null && herd.ChrAddress.Area.Contains(SearchInput)) { HerdSearchResults.Add(herd); } } // 不用手动调用RaisePropertyChanged,ObservableCollection会自动通知UI } public async override void OnNavigatedTo(INavigationParameters parameters) { base.OnNavigatedTo(parameters); AllHerds = await herdService.GetHerds(); // 初始化ObservableCollection HerdSearchResults = new ObservableCollection<Herd>(); } }
XAML的小优化(可选)
你的XAML绑定是正常的,不过可以考虑给TextChanged事件传递输入文本参数,这样不需要依赖SearchInput属性也能拿到搜索值(当前方式也没问题,只是可选优化):
<b:EventToCommandBehavior EventName="TextChanged" Command="{Binding SearchChrOrAddressCommand}" EventArgsConverter="{StaticResource TextChangedEventArgsConverter}" CommandParameter="{Binding ., Converter={StaticResource TextChangedEventArgsConverter}}"/>
另外别忘了处理空值情况——比如herd.ChrAddress可能为null,直接访问Area会引发异常,我在修改后的代码里加了空值检查。
内容的提问来源于stack exchange,提问作者Perfechte

