INotifyPropertyChangedを実装し、3つのプロパティ(1つのint、1つの文字列、および1つのbool)を持つカスタムオブジェクト(MyObject)があります。そのオブジェクトのコードは次のとおりです。
public class MyObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
{
PropertyChanged(this, e);
}
}
private int _Index;
public int Index
{
get { return _Index; }
set
{
if (_Index == value)
{
return;
}
_Index = value;
OnPropertyChanged(new PropertyChangedEventArgs("Index"));
}
}
private string _Name;
public string Name
{
get { return _Name; }
set
{
if (_Name == value)
{
return;
}
_Name = value;
_Modified = true;
OnPropertyChanged(new PropertyChangedEventArgs("Name"));
}
}
private bool _Modified;
public bool Modified
{
get { return _Modified; }
set
{
if (_Modified == value)
{
return;
}
_Modified = value;
OnPropertyChanged(new PropertyChangedEventArgs("Modified"));
}
}
public MyObject()
{
}
public MyObject(int index, string number, bool modified)
{
Index = index;
Number = number;
Modified = modified;
}
}
簡単に言うと、これらのオブジェクトのBindingListを次のようにDataGridViewに接続しています。
BindingList<MyObject> myObjectList = new BindingList<MyObject>();
BindingSource bindingSourceForMyObjects = new BindingSource();
bindingSourceForMyObjects.DataSource = myObjectList;
dataGridViewMyObjects.DataSource = bindingSourceForMyObjects;
アプリケーションを実行すると、myObjectListに100,000個のオブジェクト(ファイルから読み取ったもの)が入力され、DataGridViewに表示されます。DataGridViewには、オブジェクトの文字列プロパティを表示する列が1つしかありません。ユーザーがDataGridViewのすべての行を選択して、それらを「削除」したい場合があります。オブジェクトが実際に削除されるのではなく、100,000個すべてのオブジェクトの文字列プロパティがstring.Emptyに設定されるため、削除という用語の前後に引用符を使用します。今、私はこのコードを使用してその操作を実行します:
myObjectList.ToList().ForEach(c => c.Name = string.Empty);
この操作は、完了するまでに約55秒かかります。私も試しました:
foreach (DataGridViewRow row in dataGridViewMyObjects.SelectedRows)
{
row.Cells["NAME"].Value = string.Empty;
}
これには49秒と少し時間がかかりますが、それでも長い操作です。ちなみに、私は次のようにbindingSourceForMyObjects用に定義されたListChangedイベントハンドラーも持っています。
private void bindingSourceForMyObjects_ListChanged(object sender, ListChangedEventArgs e)
{
if (e.ListChangedType == ListChangedType.ItemChanged)
{
dataGridViewMyObjects.Rows[e.NewIndex].DefaultCellStyle.BackColor = Color.Red;
dataGridViewMyObjects.Rows[e.NewIndex].DefaultCellStyle.ForeColor = Color.White;
}
}
ご覧のとおり、これを使用して、基になるオブジェクトのリストにプログラムで変更を加えたときに、DataGridViewで変更された行を視覚的に示しています(すべてをstring.Emptyに設定した場合と同じです)。これにより、すべてのオブジェクトを「削除」するときにオーバーヘッドが追加されますが、このイベントハンドラーがなくても、操作に時間がかかります。
最後に、私のWinFormsアプリケーションは現在シングルスレッドですが、そうするのが理にかなっているコードをマルチスレッド化することを計画しています。この操作はそのようなケースの1つかもしれませんが、私がその道を進む前に、この操作のパフォーマンスを向上させるために私が見逃している(または実行する必要のないことを実行している)何かがありますか?完了するのにほぼ1分かかりますか?それとも、100,000個のオブジェクトを処理するという性質だけですか?