Добавление второго DatagridViewRow приводит к клонам - PullRequest
2 голосов
/ 06 января 2012

Я столкнулся с интересной проблемой. Когда я добавляю только один DataGridViewRow в DataGridView, все работает как положено: DataGridView.Rows [0] - это строка, которая была добавлена. Когда я добавляю второй DataGridviewRow, каким-то образом фактические DataGridViewRow больше не добавляются, а вместо этого добавляются клоны. Клоны, которые кажутся совершенно одинаковыми, но на самом деле не являются одним и тем же объектом.

Так что я хотел бы знать, почему это так, откуда происходит такое поведение и, если возможно, как остановить добавление клонов вместо реальных строк. Я просмотрел код для DataGridViewRowCollection с Reflector, но не смог найти ничего подозрительного - но, возможно, я что-то упустил.

Вот пример кода, который повторяет проблему:

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 ]

2 голосов
/ 06 января 2012

Свойство Item класса DataGridViewRowCollection создает клон 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;
}

Вот полный источник этого свойства (из Reflection):

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 в следующей статье (начиная с «Использование общих строк»):

http://msdn.microsoft.com/en-us/library/ha5xt0d9.aspx

0 голосов
/ 06 января 2012

Когда вы делаете:

 DataGridViewRow drFirst = new DataGridViewRow();

значение индекса этой строки равно -1 в объекте drFirst.но когда вы добавляете его в коллекцию строк, например:

 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.

[ОБНОВЛЕНИЕ]

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...