2013-01-23 67 views
2

我有一个实现INotifyPropertyChanged并具有三个属性(一个int,一个字符串和一个布尔)的自定义对象(MyObject)。下面是这个对象的代码:修改绑定到DataGridView的大型数据集需要很长时间?

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

要长话短说,我有这些对象迷上了一个DataGridView这样的一个的BindingList:

BindingList<MyObject> myObjectList = new BindingList<MyObject>(); 
BindingSource bindingSourceForMyObjects = new BindingSource(); 

bindingSourceForMyObjects.DataSource = myObjectList; 
dataGridViewMyObjects.DataSource = bindingSourceForMyObjects; 

当我的应用程序运行时,myObjectList会填充100,000个对象(从文件中读取)并显示在我的DataGridView中。我只在DataGridView中有一列显示我的对象的字符串属性。有可能我的用户可能想要选择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应用程序目前是单线程的,但我计划使用多线程代码,这样做有意义。这个操作可能是其中一种情况,但在我走下那条路之前,还有什么我错过的(或者我不需要这样做),这会提高这个操作的性能,花费近一分钟才能完成?或者,这只是处理100,000个物体的性质?

+0

你能打破在'.ToList()花费的时间'VS中花费的时间' .ForEach(c => ...)'? –

+1

也'c.Name'属性在其setter中做任何事情或只是一个自动属性? –

+0

.ToList()需要<.005秒。剩下的时间用在.ForEach()中。关于c.Name,除了赋值之外,它的唯一一件事是将对象的bool属性设置为true(我使用bool属性来跟踪哪些对象是脏的并且需要刷新到磁盘)。 – user685869

回答

2

@ User685869感谢张贴扩展的对象。

做了一些快速测试的例子后,似乎提高PropertyChanged事件导致放缓。删除对它的呼叫会导致操作在一秒钟或两秒内完成,以便在我的电脑上记录100k条记录。

即使没有事件处理程序,也会发生这种情况。

我认为你已经实现了接口,因为你需要它;如果你没有,那么删除它将解决你的问题。

我可以建议的唯一解决方案是创建一个boolean变量,您可以将其设置为true以防止在进行批量更新并在切换回正常后引发事件。这样做的缺点是,在进行批量操作时没有发生任何事件。

例如: -

为MyObject

public boolean bulk = false; 
public string Name 
{ 
    get { return _Name; } 
    set 
    { 
     if (_Name == value) 
     { 
      return; 
     } 

     _Name = value; 
     _Modified = true; 
     OnPropertyChanged(new PropertyChangedEventArgs("Name")); 
    } 
} 

父代码

_bindingList.ToList().ForEach(c => 
    { 
     c.bulk = true; 
     c.Name = string.Empty; 
     c.bulk = false; 
    }); 
+0

谢谢!我想我可以做出类似的工作。通常情况下,我只需要将DataGridView中所做的更改推回到对象列表中。有几种情况导致我通过INotifyPropertyChanged添加双向绑定,但是我可以通过您的建议解决这些问题。 – user685869

1

试试这个:

dataGridView1.SuspendLayout(); 
     //do changes 
     dataGridView1.ResumeLayout(); 
+0

不幸的是,这并不能真正改善我的表现。尽管如此,它的确削减了1.5秒。感谢您的建议。 – user685869

相关问题