数据网格中的 CurrentRow 在选择不同的行后给出第一行
CurrentRow in Data Grid giving first row after Selecting differant Row
我有一个 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 停留在顶行。如果我先左键单击该行然后右键单击同一行,它确实有效。
您描述的问题来自 cms_DGV_Remove_Click
事件。当用户 right-clicks 在网格上时,这不会使光标下方的 cell/row 成为网格的 CurrentRow.
即使 dgv_Test_MouseDown
方法中的代码将行设置为“selected”……它不一定是“当前”行。网格 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;
}
}
}
发布的代码似乎并没有真正删除该行,但是下面是上下文菜单“删除”事件的外观......
下面应该适用于 non-data 绑定网格以及具有数据绑定的网格 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;
}
}
我猜这就是您正在寻找的行为。用户 right-clicks 进入网格,光标下的行被 select 编辑,上下文菜单“删除”弹出。用户可以“select”删除以删除该行或单击上下文菜单以外的地方以取消删除。
希望这是有道理的。
我有一个 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 停留在顶行。如果我先左键单击该行然后右键单击同一行,它确实有效。
您描述的问题来自 cms_DGV_Remove_Click
事件。当用户 right-clicks 在网格上时,这不会使光标下方的 cell/row 成为网格的 CurrentRow.
即使 dgv_Test_MouseDown
方法中的代码将行设置为“selected”……它不一定是“当前”行。网格 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;
}
}
}
发布的代码似乎并没有真正删除该行,但是下面是上下文菜单“删除”事件的外观......
下面应该适用于 non-data 绑定网格以及具有数据绑定的网格 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;
}
}
我猜这就是您正在寻找的行为。用户 right-clicks 进入网格,光标下的行被 select 编辑,上下文菜单“删除”弹出。用户可以“select”删除以删除该行或单击上下文菜单以外的地方以取消删除。
希望这是有道理的。