I am trying to use the search navigation on a collection view in an MAUI project. I, however, have put myself into a bind.
When I try to search for some content, I get the error:
System.InvalidOperationException: 'Collection was modified; enumeration operation may not execute.'
Below is the view and ViewModel:
The View:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="KigooPCMauiSimple.Views.PropertyPage"
xmlns:viewModel="clr-namespace:KigooPCMauiSimple.ViewModels.AppViewModel"
Title="Properties">
<ContentPage.BindingContext>
<viewModel:PropertiesViewModel/>
</ContentPage.BindingContext>
<StackLayout >
<SearchBar HorizontalOptions="FillAndExpand"
VerticalOptions="Start"
Placeholder="Search Property"
BackgroundColor="{AppThemeBinding Light={StaticResource Primary},
Dark={StaticResource Gray500}}"
Text="{Binding SearchTerm, Mode=TwoWay}"
SearchCommand="{Binding SearchNameCommand}"
/>
<ListView ItemsSource="{Binding Properties}"
Margin="00,10,00,00"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
>
<ListView.ItemTemplate >
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer CommandParameter="{Binding .}"
Command="{Binding Source={RelativeSource AncestorType={x:Type viewModel:PropertiesViewModel}},Path=GoToDetailsCommand}"/>
</StackLayout.GestureRecognizers>
<Image HeightRequest="75" WidthRequest="75"
Aspect="AspectFill" Source="{Binding MainImageName}"/>
<StackLayout Orientation="Vertical" HorizontalOptions="StartAndExpand">
<Label Text="{Binding Name}"/>
<Label Text="{Binding Address}" FontSize="Subtitle"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
And the Viewmodel
using CommunityToolkit.Mvvm.ComponentModel;
using KigooPCMauiSimple.Models;
using KigooPCMauiSimple.Services;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using CommunityToolkit.Mvvm.Input;
using System.Threading.Tasks;
using KigooPCMauiSimple.KigooTask;
using KigooPCMauiSimple.Views;
namespace KigooPCMauiSimple.ViewModels.AppViewModel
{
public partial class PropertiesViewModel : BasePageViewModel
{
public PropertiesViewModel()
{
this.properties = GetProperties().Result;
}
[ObservableProperty]
ObservableCollection<Property> properties;
[ObservableProperty]
Property selectedItem;
[ObservableProperty]
public string searchTerm;
[RelayCommand]
public void SearchName()
{
if (string.IsNullOrEmpty(searchTerm))
{
searchTerm = string.Empty;
}
else
{
var zeSource = GetProperties().Result;
searchTerm = searchTerm.ToLowerInvariant();
var fiteredItems = zeSource.Where(m =>
m.Name.ToLowerInvariant().Contains(searchTerm)
|| m.Address.ToLowerInvariant().Contains(searchTerm));
if (fiteredItems is null)
{
foreach (var item in Properties)
{
properties.Remove(item);
}
}
else
{
foreach (var item in Properties)
{
properties.Remove(item);
}
foreach (var item in fiteredItems)
{
properties.Add(item);
}
}
}
}
[RelayCommand]
async Task GoToDetails(Property property)
{
if (property is null)
{
return;
}
var detail = GetData.GetPropertyDetail(property.Id).Result;
var description = Converters.HTMLToText(detail.Property.Description);
detail.Property.Description = description;
await Shell.Current.GoToAsync($"{nameof(DetailsPage)}", true,
new Dictionary<string, object>()
{
{"PropertyDetailViewModel",detail }
}
);
}
public static async Task<ObservableCollection<Property>> GetProperties()
{
var homeviewModel = await new PropertiesService().GetUserPropertiesViewModelAsync();
var properties = new ObservableCollection<Property>();
foreach (var item in homeviewModel.Properties)
{
properties.Add(item);
}
return properties;
}
}
}
You can clone the project and see the whole scope on Github.
I can no longer trace the fault.
CodePudding user response:
instead of doing this, which is not allowed in C# (you cannot modify a collection while you are iterating it)
foreach (var item in Properties)
{
properties.Remove(item);
}
do this
Properties.Clear();