添加第二个DatagridViewRow会导致克隆

时间:2012-01-06 10:18:48

标签: c# .net winforms datagridview

我遇到了一个有趣的问题。当我只向DataGridView添加一个DataGridViewRow时,一切都按预期工作:DataGridView.Rows [0]是添加的行。当我以某种方式添加第二个DataGridviewRow时,不再添加实际的DataGridViewRows,而是添加了克隆。克隆看起来完全相同但实际上并不是同一个对象。

所以我想知道的是,为什么会出现这种情况,如果可能的话,如何阻止克隆被添加而不是实际的行。我查看了带有Reflector的DataGridViewRowCollection的代码,但找不到任何可疑的东西 - 但也许我错过了一些东西。

这是一个复制问题的代码示例:

DataGridView dgv = new DataGridView { AllowUserToAddRows = false };

DataGridViewTextBoxColumn dgColumn = new DataGridViewTextBoxColumn();
dgv.Columns.Add(dgColumn);

DataGridViewRow drFirst = new DataGridViewRow();
dgv.Rows.Add(drFirst); // Comment this line to showcase the problem

DataGridViewRow drSecond = new DataGridViewRow();
drSecond.Tag = new object();
dgv.Rows.Add(drSecond);

// When drFirst is added this is false - when it isn't this is true (as it should always be?)
bool thisSeemsWrong = object.ReferenceEquals(dgv.Rows[dgv.Rows.Count - 1], drSecond);

// Always true
bool thisSeemsRight = object.ReferenceEquals(dgv.Rows[dgv.Rows.Count - 1].Tag, drSecond.Tag);

2 个答案:

答案 0 :(得分:2)

DataGridViewRowCollection的{​​{3}}属性会创建GridViewRow的克隆并返回该属性,因此当ReferenceEquals超过false时,DataGridViewRow row2 = (DataGridViewRow) dataGridViewRow.Clone(); 应始终为index=0一排。

if (((index == 0) && (this.items.Count() == 1))) {
      dataGridViewRow.IndexInternal = 0;
      dataGridViewRow.StateInternal = this.SharedRowState[0];
      if (((this.DataGridView != null))) {
          this.DataGridView.OnRowUnshared(dataGridViewRow);
      }
      return dataGridViewRow;
}

但如果只有一行public DataGridViewRow this[int index] { get { DataGridViewRow dataGridViewRow = this.SharedRow(index); if (dataGridViewRow.Index != -1) { return dataGridViewRow; } if ((index == 0) && (this.items.Count == 1)) { dataGridViewRow.IndexInternal = 0; dataGridViewRow.StateInternal = this.SharedRowState(0); if (this.DataGridView != null) { this.DataGridView.OnRowUnshared(dataGridViewRow); } return dataGridViewRow; } DataGridViewRow row2 = (DataGridViewRow) dataGridViewRow.Clone(); row2.IndexInternal = index; row2.DataGridViewInternal = dataGridViewRow.DataGridView; row2.StateInternal = this.SharedRowState(index); this.SharedList[index] = row2; int num = 0; foreach (DataGridViewCell cell in row2.Cells) { cell.DataGridViewInternal = dataGridViewRow.DataGridView; cell.OwningRowInternal = row2; cell.OwningColumnInternal = this.DataGridView.Columns[num]; num++; } if (row2.HasHeaderCell) { row2.HeaderCell.DataGridViewInternal = dataGridViewRow.DataGridView; row2.HeaderCell.OwningRowInternal = row2; } if (this.DataGridView != null) { this.DataGridView.OnRowUnshared(row2); } return row2; } } ,则返回相同的引用。

why

以下是此属性的完整来源(来自Reflection):

{{1}}

也许您会在以下文章中找到有关{{1}}的信息(从“使用共享行”开始):

Item

答案 1 :(得分:0)

当你这样做时:

 DataGridViewRow drFirst = new DataGridViewRow();

drFirst对象中此行的索引值为-1。 但是当你将它添加到Row集合中时:

 DataGridViewRow drFirst = new DataGridViewRow();

行集合根据集合中已存在的行数为其提供新索引。在你的情况下,索引= 0。

类似地,对于drSecond,在创建时索引值为-1,但是当您将其添加到行集合时,索引值将更改为1.

所以行:

bool thisSeemsWrong = object.ReferenceEquals(dgv.Rows[dgv.Rows.Count - 1], drSecond);

正在比较具有不同索引值的两个对象,因此它们将不同,因此返回false。 但这一行:

bool thisSeemsRight = object.ReferenceEquals(dgv.Rows[dgv.Rows.Count - 1].Tag, drSecond.Tag);

只是比较一个尚未更改的属性Tag并返回true。

[UPDATE]

DataGridViewRow drFirst = new DataGridViewRow();
//dgv.Rows.Add(drFirst); //if you comment this line then the thisSeemsWrong is true that's right because it's now comparing the row you add which is drSecond with drSecond

DataGridViewRow drSecond = new DataGridViewRow();
drSecond.Tag = new object();
dgv.Rows.Add(drSecond);

// When drFirst is added this is false - when it isn't this is true (as it should always be?)
bool thisSeemsWrong = object.ReferenceEquals(dgv.Rows[dgv.Rows.Count - 1], drSecond);

DataGridViewRow drFirst = new DataGridViewRow();
dgv.Rows.Add(drFirst); // Now because you have added the first row as drFirst, look what you are comparing against in thisSeemsWrong, you are comparing Row[0] which is drFirst with drSecond which will always be false. You either have to compare Row[1] with drSecond or Row[0] with drFirst??

DataGridViewRow drSecond = new DataGridViewRow();
drSecond.Tag = new object();
dgv.Rows.Add(drSecond);

// When drFirst is added this is false - when it isn't this is true (as it should always be?)
bool thisSeemsWrong = object.ReferenceEquals(dgv.Rows[dgv.Rows.Count - 1], drSecond);