在MVVM中将SearchBar与ObservableCollection一起使用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在MVVM中将SearchBar与ObservableCollection一起使用相关的知识,希望对你有一定的参考价值。
我已经在我的应用程序中创建了一个搜索页面,我希望能够在ViewModel中的ObservableCollection
中搜索项目并将其显示在CollectionView
上。到目前为止,这是我所做的,并且每次运行应用程序时都会出现异常,即System.Reflection.TargetInvocationException: 'Exception has been thrown by the target of an invocation.'
。SearchPage XAML
<!--Doctors Search Result-->
<Grid Grid.Row="1">
<CollectionView ItemsSource="Binding RecentDoctors">
<CollectionView.ItemsLayout>
<ListItemsLayout Orientation="Vertical" ItemSpacing="15"/>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Horizontal">
<!--Image-->
<Frame BackgroundColor="Black"
HeightRequest="20"
WidthRequest="20"
CornerRadius="100"
Margin="20,0,0,0"
HorizontalOptions="Start"
VerticalOptions="Center"
IsClippedToBounds="True">
<Image HorizontalOptions="Center"
VerticalOptions="Center"/>
</Frame>
<StackLayout Orientation="Vertical"
VerticalOptions="Center"
Spacing="-3">
<!--Fullname-->
<Label Text="Binding DoctorsName"
FontSize="19"
FontAttributes="Bold"/>
<!--Specialization-->
<Label Text="Binding Specialization"
FontSize="14"
TextColor="LightGray"/>
</StackLayout>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
<!--Doctors Search Bar-->
<Grid Grid.Row="0" ColumnSpacing="0" RowSpacing="0">
<pancake:PancakeView BackgroundColor="#0F8DF4"
HasShadow="True">
<Grid>
<!--The SearchBar-->
<renderers:CustomSearchBar x:Name="doctorsSearchBar"
Placeholder="Search Doctors by Name, Specialization"
VerticalOptions="Center"
FontSize="17"
TextColor="Black"
WidthRequest="320"
Text="Binding SearchedText"
SearchCommand="Binding SearchBarCommand"
SearchCommandParameter="Binding Text, Source=x:Reference doctorsSearchBar"/>
</Grid>
</pancake:PancakeView>
</Grid>
SearchPage ViewModel
public class TelemedSearchPageViewModel : BaseViewModel
private string _searchedText;
public string SearchedText
get return _searchedText;
set
_searchedText = value;
OnPropertyChanged();
Search();
public ObservableCollection<RecentDoctorsInfo> RecentDoctors get; set; = new ObservableCollection<RecentDoctorsInfo>();
public ICommand SearchBarCommand get; set;
/// <summary>
/// Main Constructor
/// </summary>
public TelemedSearchPageViewModel()
SearchBarCommand = new RelayCommand(Search);
//RecentDoctorsList
RecentDoctors.Add(new RecentDoctorsInfo()
DoctorsName = "Steven Strange",
Specialization = "Sorcerer Supreme",
Location = "177a Bleecker St. | USA"
);
RecentDoctors.Add(new RecentDoctorsInfo()
DoctorsName = "Peter Parker",
Specialization = "Spiderman",
Location = "177a Bleecker St. | USA"
);
RecentDoctors.Add(new RecentDoctorsInfo()
DoctorsName = "Bruce Banner",
Specialization = "The Hulk",
Location = "177a Bleecker St. | USA"
);
RecentDoctors.Add(new RecentDoctorsInfo()
DoctorsName = "Reed Richards",
Specialization = "Mr.Fantastic",
Location = "177a Bleecker St. | USA"
);
#region METHODS
public void Search()
if (RecentDoctors != null && RecentDoctors.Count >0)
var temp = RecentDoctors.Where(x => x.DoctorsName.ToLower().Contains(SearchedText.ToLower()));
foreach (var item in temp)
RecentDoctors.Add(item);
#endregion
Edit3:
if (RecentDoctors != null && RecentDoctors.Count > 0)
var results = RecentDoctors.Where(x => x.DoctorsName.ToLower().Contains(SearchedText.ToLower()));
SearchResults.Clear();
foreach (RecentDoctorsInfo item in results)
SearchResults.Add(item);
else
RecentDoctors.Clear();
答案
如果要在用户键入时执行搜索,则应使用doscs建议的行为
public class SearchBarTextChangedBehavior : Behavior<SearchBar>
protected override void OnAttachedTo(SearchBar bindable)
base.OnAttachedTo(bindable);
bindable.TextChanged += this.SearchBar_TextChanged;
protected override void OnDetachingFrom(SearchBar bindable)
base.OnDetachingFrom(bindable);
bindable.TextChanged -= this.SearchBar_TextChanged;
private void SearchBar_TextChanged(object sender, TextChangedEventArgs e)
((SearchBar)sender).SearchBarCommand?.Execute(e.NewTextValue);
然后将行为附加到您的SearchBar
<renderers:CustomSearchBar
x:Name="doctorsSearchBar"
Placeholder="Search Doctors by Name, Specialization"
VerticalOptions="Center"
FontSize="17"
TextColor="Black"
WidthRequest="320"
Text="Binding SearchedText"
SearchCommand="Binding SearchBarCommand">
<renderers:CustomSearchBar.Behaviors>
<behaviors:SearchBarTextChangedBehavior />
</renderers:CustomSearchBar.Behaviors>
</renderers:CustomSearchBar>
另一方面,您应该创建原始列表的私有副本,并添加与公共收藏夹相同的项目
private List<RecentDoctorsInfo> originalRecentDoctorsList = new List<RecentDoctorsInfo>();
public ObservableCollection<RecentDoctorsInfo> RecentDoctors get; set; = new ObservableCollection<RecentDoctorsInfo>();
public ICommand SearchBarCommand get; set;
public TelemedSearchPageViewModel()
SearchBarCommand = new RelayCommand(Search);
//RecentDoctorsList
RecentDoctors.Add(new RecentDoctorsInfo()
DoctorsName = "Steven Strange",
Specialization = "Sorcerer Supreme",
Location = "177a Bleecker St. | USA"
);
RecentDoctors.Add(new RecentDoctorsInfo()
DoctorsName = "Peter Parker",
Specialization = "Spiderman",
Location = "177a Bleecker St. | USA"
);
RecentDoctors.Add(new RecentDoctorsInfo()
DoctorsName = "Bruce Banner",
Specialization = "The Hulk",
Location = "177a Bleecker St. | USA"
);
RecentDoctors.Add(new RecentDoctorsInfo()
DoctorsName = "Reed Richards",
Specialization = "Mr.Fantastic",
Location = "177a Bleecker St. | USA"
);
// Backup copy list.
originalRecentDoctorsList.Add(new RecentDoctorsInfo()
DoctorsName = "Steven Strange",
Specialization = "Sorcerer Supreme",
Location = "177a Bleecker St. | USA"
);
originalRecentDoctorsList.Add(new RecentDoctorsInfo()
DoctorsName = "Peter Parker",
Specialization = "Spiderman",
Location = "177a Bleecker St. | USA"
);
originalRecentDoctorsList.Add(new RecentDoctorsInfo()
DoctorsName = "Bruce Banner",
Specialization = "The Hulk",
Location = "177a Bleecker St. | USA"
);
originalRecentDoctorsList.Add(new RecentDoctorsInfo()
DoctorsName = "Reed Richards",
Specialization = "Mr.Fantastic",
Location = "177a Bleecker St. | USA"
);
最后,您的Search
方法应清除公共集合(您正在显示的集合),并使用私有作为备份
private void Search()
if (!string.IsNullOrEmpty(SearchedText))
var filteredDoctors = RecentDoctors
.Where(x =>
x.DoctorsName.ToLower().Contains(SearchedText.ToLower()))
.ToList();
RecentDoctors.Clear();
foreach(var recentDoctor in filteredDoctors)
RecentDoctors.Add(recentDoctor);
else
// This is when you clean the text from the search
RecentDoctors.Clear();
foreach(var originalRecentDoctor in originalRecentDoctorsList)
RecentDoctors.Add(originalRecentDoctor);
以上是关于在MVVM中将SearchBar与ObservableCollection一起使用的主要内容,如果未能解决你的问题,请参考以下文章
如何在新的 navigationItem.searchController 中将 SearchBar 居中?