2016-04-01 21 views
2

foreachループ中にObservableCollectionのアイテムを更新する際に問題が発生しています。基本的に私はObservableCollectionの従業員を抱えています。彼らは建物内にいるかどうかを決定するフィールドをモデルに持っています。Foreachループでのコレクションの変更C#

私はこの状態に変化があるかどうかをすべての従業員をチェックするために常にデータベーステーブルを調べています。これは私がC#でこれを行う方法です。

public ObservableCollection<EmployeeModel> EmployeesInBuilding {get; set; } 
public ObservableCollection<EmployeeModel> Employees {get; set; } 

var _employeeDataService = new EmployeeDataService(); 
EmployeesInBuilding = _employeeDataService.GetEmployeesInBuilding(); 
foreach (EmployeeModel empBuild in EmployeesInBuilding) 
{ 
    foreach (EmployeeModel emp in Employees) 
    { 
     if (empBuild.ID == emp.ID) 
     { 
      if (empBuild.InBuilding != emp.InBuilding) 
      { 
       emp.InBuilding = empBuild.InBuilding; 
       int j = Employees.IndexOf(emp); 
       Employees[j] = emp; 
       employeesDataGrid.Items.Refresh(); 
      } 
     } 
    } 
} 

これは正しく、私は既存のObservableCollectionを更新するために行くときしかし、私は例外を取得、2 ObseravbleCollections間の変化をピックアップ:Collection was modified; enumeration operation may not execute.

は、どのように私はこれを防ぐ、まだ元のコレクションを変更することができます?

+4

インデックス位置 'j'の' Employees'に 'emp'がすでに含まれている場合、' Employees [j] = emp'を呼び出すのは意味がありません。コレクション要素を置き換える代わりに、 'InBuilding'プロパティが変更されたときにEmployeeModelクラスに' INotifyPropertyChanged'インタフェースを実装させ、 'PropertyChanged'イベントを発生させるべきです。 – Clemens

+0

私はこの部分について疑いがあります。 'int j = Employees.IndexOf(emp);従業員[j] = emp; '。 'j'インデックスの要素は変更されません。 'foreach(EmployeeModel emp in Employees)'の代わりに 'for'ループを使うと、あなたのコードは例外なく動作します。 – ASh

答えて

5

要素のプロパティを設定するだけで、Employeesコレクション内の要素を置き換える必要はありません。

その代わりに、あなたのEmployeeModelクラスがINotifyPropertyChangedインタフェースを実装する必要がありますし、InBuildingプロパティの変更時にPropertyChangedイベントを発生させる:

public class EmployeeModel : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    private bool inBuilding; 
    public bool InBuilding 
    { 
     get { return inBuilding; } 
     set 
     { 
      if (inBuilding != value) 
      { 
       inBuilding = value; 
       OnPropertyChanged("InBuilding"); 
      } 
     } 
    } 

    private void OnPropertyChanged(string propertyName) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    ... 
} 

今すぐ更新コードの内部ループがこれに減らすことができます。

foreach (var emp in Employees) 
{ 
    if (empBuild.ID == emp.ID) 
    { 
     emp.InBuilding = empBuild.InBuilding; 
    } 
} 

それとも、このような全体の更新ループ書き込み:

foreach (var empBuild in EmployeesInBuilding) 
{ 
    var emp = Employees.FirstOrDefault(e => e.ID == empBuild.ID); 

    if (emp != null) 
    { 
     emp.InBuilding = empBuild.InBuilding; 
    } 
} 
関連する問題