从wp8中的可观察集合中删除项目

本文关键字:集合 删除项目 观察 wp8 | 更新日期: 2023-09-27 18:20:59

我有一个可观察的集合链接到一个LongListItemSelector,这些部分工作得很好。

我使用复选框选择方法,它在后台构建一个列表,当我单击"删除"按钮时,该列表将作为参数传递。在ViewModel中定义的Delete按钮方法中,我有以下代码:

foreach (FavoriteItemViewModel item in selectedFavorites)
{
    FavoriteItemViewModel itemToDeleted = this.Favorites
        .FirstOrDefault<FavoriteItemViewModel>(m =>
            m.Description.ToLowerInvariant() == item.Description.ToLowerInvariant());
    if (itemToDeleted != null)
        this.Favorites.Remove(itemToDeleted);
}

其中selectedFavorites属于List<Object>类型,包含通过复选框选择的项目。

每个"对象"的类型都是FavoriteItemViewModel。由于列表中包含的"对象"与我的收藏夹ObservableCollection中包含的略有不同,我确保首先根据它们的描述在收藏夹中找到项目,因为这应该匹配。

如果找到,我会删除它,但我可以这样做,即该项目实际上并没有从Favorites可观察集合中删除。

我知道你不能使用For Each来循环浏览一个可观察的集合,并试图直接删除一个项目,但我不会这么做。

我尝试过不同的场景,但都没有成功。

你知道我做错了什么吗?

谢谢。

从wp8中的可观察集合中删除项目

您可以使用List<T>的实用构造函数来构造新的List,其中包含来自现有List的项,而无需手动foreach循环。这样的东西应该足够了:

private void DeleteAction(object actionParameter)
{
    List<object> selectedFavorites = 
                    new List<object>(actionParameter as List<object>);
    foreach (var item in selectedFavorites)
    {
        this.Favorites.Remove((FavoriteItemViewModel)item);
    }
}

通常,我们不需要调用Clear()并将selectedFavorites设置为null,因为变量是它在本地上下文中自行声明的,所以在方法执行完成后不久,它就可以进行垃圾收集了。

问题解决后,唯一能做的就是使用removeall-linq而不是其他列表。

Favorites.RemoveAll(a => selectedFavorites.Exists(w => ((FavoriteItemViewModel)w).Description == a.Description));

我解决了这个问题。。。我犯了几个错误!

第一个问题:我的财产收藏夹是如何定义的:

    public ObservableCollection<FavoriteItemViewModel> Favorites
    {
        get
        {
            return _favorites ?? (this.LoadFavorites(App.MainViewModel.Favorites));
        }
        set
        {
            _favorites = value;
        }
    }

get部分从未实际设置内部变量,因此从MainViewModel中的Favorites集合中一次又一次地重新加载数据。

我把它从:

return _favorites ?? (this.LoadFavorites(App.MainViewModel.Favorites));

return _favorites ?? (_favorites = this.LoadFavorites(App.MainViewModel.Favorites));

Doooh!!

第二个问题:

因此,虽然下面并没有直接从我的可观察集合中删除对象

private void DeleteAction(object actionParameter)
{
    List<object> selectedFavorites = actionParameter as List<object>;
    foreach (FavoriteItemViewModel item in selectedFavorites)
    {
        FavoriteItemViewModel itemToDelete = 
        this.Favorites.FirstOrDefault<FavoriteItemViewModel>
        (m => m.Description.ToLowerInvariant() == item.Description.ToLowerInvariant());
        if (itemToDelete != null)
          this.Favorites.Remove(itemToDelete);
   }
 }

通过CommandParameter传递的参数actionParameter,即List,是从我的LongListSelector中选择的对象的列表(用于处理MVVM的自定义对象)。无论何时选择或取消选择某个项目,都会直接影响此列表。

我假设这个参数是通过值传递的,但事实并非如此,实际上是通过引用传递的。

所以呼叫

this.Favorites.Remove(itemToDelete)

当我第二次将其从可观察集合中删除时,它也不起作用,它还影响了分配给actionParameter变量的局部变量selectedFavorites列表,我得到了典型的错误:

An exception of type 'System.InvalidOperationException' occurred in 
mscorlib.ni.dll but was not handled in user code
Additional information: Collection was modified; enumeration 
operation may not execute.`

如果我使用for循环,而我没有得到错误,假设我选择了2个项目,第二次我从收藏夹可观察集合中删除第一个项目,selectedFavorites.count从2降到1,并导致我的for循环过早结束。

因此,唯一的解决方案是首先基于selectedFavorites列表构建一个单独的列表,然后简单地使用for each循环。

最后的代码如下:

    private void DeleteAction(object actionParameter)
    {
        List<object> selectedFavorites = actionParameter as List<object>;
        List<FavoriteItemViewModel> myList = new List<FavoriteItemViewModel>();
        Favorites.RemoveAll(a => selectedFavorites.Exists(w =>     ((FavoriteItemViewModel)w).Description == a.Description));
        myList = null;
    }

这是意料之中的事!