【问题标题】:Delete item from observable collection in wp8从 wp8 中的可观察集合中删除项目
【发布时间】:2014-09-07 00:56:03
【问题描述】:

我有一个链接到 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);
}

其中selectedFavoritesList&lt;Object&gt; 类型,包含通过复选框选择的项目。

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

如果找到,我将其删除,但我可以确保该项目实际上并未从 Favorites 可观察集合中删除。

我了解您不能使用 For Each 循环遍历可观察的集合并尝试直接删除项目,但我没有这样做。

我尝试了不同的场景,但无济于事。

任何想法我做错了什么?

谢谢。

【问题讨论】:

  • 你怎么知道它没有被删除?检查Remove 的返回值,如果该项目被删除,它将是true。您发布的代码中没有任何错误。

标签: c# .net windows-phone-8 observablecollection


【解决方案1】:

您可以使用List&lt;T&gt; 的参数化构造函数来构造新的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,因为它是在本地上下文中自行声明的变量,因此在方法执行完成后很快就会有资格进行垃圾回收。

【讨论】:

    【解决方案2】:

    随着问题的解决,唯一可以做的就是使用 removeall linq 而不是其他列表。

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

    【讨论】:

      【解决方案3】:

      我发现了问题...我犯了几个错误!

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

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

      get 部分从未实际设置内部变量,因此会一遍又一遍地从 MainViewModel 中保存的收藏夹集合中重新加载数据。

      我把它改成:

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

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

      哇!!

      第二个问题:

      因此,虽然以下不是直接从我的可观察集合中删除对象

      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 即List 传递的参数actionParameter 是从我的LongListSelector 中选择的对象的列表(用于处理MVVM 的自定义对象)。 This List is directly affected whenever an item is selected or unselected.

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

      这样呼唤

      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;
          }
      

      这按预期工作!

      【讨论】:

      • 无需建立该列表。你可以简单地拥有一个 for (int i = 0; i
      • 从未想过!谢谢。我明天在电脑前更新答案!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多