CurrentRow в таблице данных дает первую строку после выбора отличающейся строки - PullRequest
0 голосов
/ 20 июня 2019

У меня есть проект C # (VS 2017), в котором используется Data Grid View для отображения данных в списке объектов. Используя contextMenuStrip, я хочу иметь возможность щелкнуть правой кнопкой мыши по строке и удалить ее из таблицы данных и основного источника данных.

У меня есть contextMenuStrip, установленный в Свойствах Datagridview с одним элементом со следующими методами для обработки событий.

    private void dgv_Test_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Right)
        {
            var hti = dgv_Test.HitTest(e.X, e.Y);

            dgv_Test.ClearSelection();
            dgv_Test.Rows[hti.RowIndex].Selected = true;
        }
    }

    private void cms_DGV_Remove_Click(object sender, EventArgs e)
    {
        MessageBox.Show("Content Menu Clicked on Remove Option");

        PersonModel temp = (PersonModel)dgv_Test.CurrentRow.DataBoundItem;

        string msg = $"The index for the selected Person is {temp.Id}.";
        MessageBox.Show(msg);

    }

Я ожидаю, что это отправит текущую строку в строку, по которой щелкнули правой кнопкой мыши. Этого не происходит, так как CurrentRow находится в верхнем ряду. Это сработает, если я сначала щелкну левой кнопкой мыши по строке, а затем правой кнопкой мыши по той же строке.

1 Ответ

0 голосов
/ 21 июня 2019

Описываемая вами проблема связана с событием cms_DGV_Remove_Click.Когда пользователь щелкает правой кнопкой мыши по сетке, это НЕ сделает ячейку / строку под курсором сеткой CurrentRow., хотя код в методе dgv_Test_MouseDown устанавливает строку как «выбранную»….это не обязательно будет «текущий» ряд.Свойство grids CurrentRow доступно только для чтения, и вы не можете напрямую установить его из своего кода.

Учитывая это, ясно, что получение координат мыши «по отношению к сетке» из контекстного меню займетмало усилий, так как его координаты являются глобальными.Вы, видимо, заметили это по подключению события grid MouseDown.Это событие облегчает захват позиции мыши относительно сетки.Проблема в том ... вы НЕ сохраняете эту информацию.Ко времени срабатывания контекстного меню эта информация теряется.

Решение: сделать глобальную информацию DataGridView.HitTest.Затем установите его каждый раз, когда пользователь щелкает правой кнопкой мыши в сетке.Если эта глобальная переменная установлена, при срабатывании контекстного меню она будет знать, под какой строкой находится курсор.

DataGridView.HitTestInfo HT_Info;   // <- Global variable

private void dgv_Test_MouseDown(object sender, MouseEventArgs e) {
  if (e.Button == MouseButtons.Right) {
    HT_Info = dgv_Test.HitTest(e.X, e.Y);
    if (HT_Info.RowIndex >= 0) {
      dgv_Test.ClearSelection();
      dgv_Test.Rows[HT_Info.RowIndex].Selected = true;
    }
  }
}

Не похоже, что опубликованный код фактически удаляет строку, однако ниже приведен контекстменю «удалить» событие может выглядеть…

Ниже должна работать сетка без привязки к данным, а также сетка с привязкой к данным DataTable.

private void cms_DGV_Remove_Click(object sender, EventArgs e) {
  if (HT_Info.RowIndex >= 0) {
    dgv_Test.Rows.Remove(dgv_Test.Rows[HT_Info.RowIndex]);
  }
}

Если вы используете List<T>, метод удаления может выглядеть примерно так:

private void cms_DGV_Remove_Click(object sender, EventArgs e) {
  if (HT_Info.RowIndex >= 0) {
    PersonModel targetPerson = (PersonModel)dgv_Test.Rows[HT_Info.RowIndex].DataBoundItem;
    AllPersons.Remove(targetPerson);
    dgv_Test.DataSource = null;
    dgv_Test.DataSource = AllPersons;
  }
}

Я предполагаю, что это поведение, которое вы ищете.Пользователь щелкает правой кнопкой мыши в сетке, выбирается строка под курсором и появляется контекстное меню «удалить».Пользователь может «выбрать» удаление, чтобы удалить строку, или щелкнуть в контекстном меню, чтобы отменить удаление.

Надеюсь, что это имеет смысл.

...