【问题标题】:Avoid to overwrite values inside ObservableCollection (C#, WPF)避免覆盖 ObservableCollection (C#, WPF) 中的值
【发布时间】:2018-09-24 10:22:51
【问题描述】:

我有工作日清单

绑定到DataGrid:

ItemsSource="{Binding Path=MyConceptItems}"

然后我从 json 其他列表中获取并尝试使用日期进行匹配:

public ObservableCollection<MyDataConcept> MyConceptItems { get; set; }

public void GetSheet(string fd, string ld){
 string period = "\"" + fd + "\",\"" + ld + "\"";
 string result = Task.Run(() => MyMethodAsync("getsheet", GetApiKeyAsync(), "," + period)).
                                GetAwaiter().GetResult();
 MyObject resultparsed = new JavaScriptSerializer().Deserialize<MyObject>(result);

  foreach (var item in resultparsed.result.items) {                
   foreach (var existingItem in MyConceptItems) {
    if (existingItem.DateColumn == item.entryDate) {
                    existingItem.PColumn = item.pName;
                    existingItem.TColumn = item.aName;
                    existingItem.HSpend = item.formattedDuration;
 }}}};

我的问题是:当我从 json 两个具有相同日期的结果中获取时,MyConceptItems 只显示一个(最后一个)项目,可能被覆盖。

示例

MyConecptItems:

  Date     | PColumn
2018-09-03 |  A2
2018-09-04 |  B
2018-09-05 |  C2

来自Json

   Date     | PName
2018-09-03  |  A
2018-09-03  |  A2
2018-09-04  |  B
2018-09-05  |  C
2018-09-05  |  C2

更新:

我正在尝试如下操作:

foreach (var item in resultparsed.result.items) {                
   foreach (var existingItem in MyConceptItems) {
    if (existingItem.DateColumn == item.entryDate) 
     if (existingItem.IsExist == false){
                            existingItem.IsExist = true;
                            existingItem.ProjectColumn = item.projectName;
                            existingItem.TaskColumn = item.activityName;
                            existingItem.HoursSpend = item.formattedDuration;
      }
      else
      {
      MyConceptItems.Add(new MyDataConcept(item.entryDate, item.entryDayName, 
                         item.projectName, item.activityName, item.formattedDuration); 
      } 
 }}

然后有这个消息:

System.InvalidOperationException: 
'Collection was modified; enumeration operation may not execute.'

【问题讨论】:

  • 这是因为您在循环中覆盖了这些值:existingItem.PColumn = item.pName;
  • 那我该怎么办呢?创建 MyConceptItems?
  • 所以你想显示多个具有相同日期的项目?或者你的问题是什么?您如何知道何时更新现有项目或添加新项目?
  • 如果我有一个日期以下的几个项目,我想显示所有这些,日期将相同但其他列不同(PName、TColumn 等...)
  • 更新我的问题

标签: c# wpf data-binding observable observablecollection


【解决方案1】:

在使用foreach 循环枚举集合时,您不能修改集合。试试这样的:

foreach (var item in resultparsed.result.items)
{
    var existingItem = MyConceptItems.FirstOrDefault(x => x.DateColumn == item.entryDate);
    if(existingItem != null)
    {
        //update properties...
    }
    else
    {
        //add new item
        MyConceptItems.Add(new MyDataConcept(item.entryDate, item.entryDayName,
            item.projectName, item.activityName, item.formattedDuration);
    }
}

【讨论】:

  • 我把if改成=> existingItem.IsExist == false,现在可以了....我只需要排序
  • 您的意思是要对 MyConceptItems 进行排序?
  • 是的,因为最后添加了新Item,我需要按entryDayName排序
  • 那是另一个问题。如果您还有其他问题,请提出新问题。
【解决方案2】:

您正在使用该行遍历 ObservableCollection

foreach (var existingItem in MyConceptItems) {

以这种方式循环使用集合的迭代器。然后,您将在该循环中添加一个项目:

MyConceptItems.Add(new MyDataConcept(...

在修改集合本身时不能使用集合枚举器(修改集合中项目的属性很好)。

考虑更改您的代码以使用这些方便的 IList 扩展方法之一,这些方法允许您指定谓词(选择特定对象的条件):ContainsAnySelectSingleOrDefault .如果这些方法没有返回您期望的项目,那么您可以向集合中添加一个新项目。

【讨论】:

    猜你喜欢
    • 2013-06-02
    • 2015-03-01
    • 2022-01-22
    • 1970-01-01
    • 2013-08-22
    • 2012-03-08
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    相关资源
    最近更新 更多