【问题标题】:CurrentRow in Data Grid giving first row after Selecting differant Row数据网格中的 CurrentRow 在选择不同的行后给出第一行
【发布时间】:2019-06-21 11:41:59
【问题描述】:

我有一个 C# 项目 (VS 2017),它使用数据网格视图在对象列表中显示数据。使用 contextMenuStrip 我希望能够右键单击一行并能够将其从 datagridview 和基础数据源中删除。

我在 Datagridview 的属性中设置了 contextMenuStrip,其中一项具有以下处理事件的方法。

    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 停留在第一行。如果我先左键单击该行然后右键单击同一行,它确实有效。

【问题讨论】:

    标签: c# datagridview contextmenustrip


    【解决方案1】:

    您描述的问题来自cms_DGV_Remove_Click 事件。当用户右键单击网格时,这不会使光标下方的单元格/行成为网格的CurrentRow.,即使dgv_Test_MouseDown 方法中的代码将行设置为“选中”……。它不一定是“当前”行。 grids CurrentRow 属性是只读的,不能直接从代码中设置。

    鉴于此,很明显从上下文菜单中获取“相对于网格”的鼠标坐标将需要一些努力,因为它的坐标是全局的。您显然已经从连接网格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&lt;T&gt;,则删除方法可能如下所示...

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

    我猜这是您正在寻找的行为。用户右键单击网格,光标下的行被选中,上下文菜单“删除”弹出。用户可以“选择”删除以删除该行,也可以单击离开上下文菜单以取消删除。

    希望这是有道理的。

    【讨论】:

    • JohnG,谢谢你的详细解释。这正是我理解潜在问题所需要的。我将实现使 DataGridView.HitTest 全球化。再次感谢您。
    猜你喜欢
    • 1970-01-01
    • 2013-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-09
    相关资源
    最近更新 更多