在WinForm应用程序中排序DataGridView时选择的行

Hor*_*ter 10 .net datagridview winforms c#-4.0

在WinForm应用程序C#4.0中,我有一个绑定到SortableBindingList的DataGridView.因此可以通过单击标题列进行排序 - 到目前为止一切正常;-)

问题是,所选行似乎被行号"记住".这是发生的事情:

A*  <- "Selected"
B
C
Run Code Online (Sandbox Code Playgroud)

现在排序降序,C在顶部并选中.我想要选择A:

C*  <- "Selected"
B
A   <- "Want have"
Run Code Online (Sandbox Code Playgroud)

同样的情况也是如此,选择了多行.这有解决方法吗?

Dav*_*all 11

您可以通过在排序之前存储当前所选行(或行)的值然后重新选择行来解决此问题.

您需要使用CellMouseDown事件 - 必须使用此事件,因为它是唯一一个在排序发生之前触发的事件.像ColumnHeaderMouseClick这样的替代事件都为时已晚.

在CellMouseDown事件处理程序中检查行索引是否为-1以确保选择了标头.

void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
    if (e.RowIndex == -1)
    {
        selected = dataGridView1.SelectedRows[0].Cells[0].Value.ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

我有一个类级别字段selected,用于存储所选列的唯一标识符.如果您没有唯一的ID,则可以为此添加一列并隐藏它.

然后在SortedDataGridView 的eventhandler中,您可以使用网格绑定源的.Find()方法:

void dataGridView1_Sorted(object sender, EventArgs e)
{
    if (!string.IsNullOrEmpty(selected))
    {
        int itemFound = _bindingSource.Find("name", selected);
        _bindingSource.Position = itemFound;
    }
}
Run Code Online (Sandbox Code Playgroud)

在调查这个问题时,我在MSDN论坛上找到了以下帖子,其答案使用了DataBindingComplete事件 - 我不是100%为什么他们发现必要,因为我的方法适用于我的所有测试,但您可能会发现它是一个有用的参考.


Mar*_*aus 5

这是我在 VB.NET 中的方法

Private cSelectedRow As String

Private Sub DataGridView1_CellMouseDown(sender As Object, e As DataGridViewCellMouseEventArgs) Handles DataGridView1.CellMouseDown
    If e.RowIndex = -1 AndAlso DataGridView1.SelectedRows.Count > 0 Then
        cSelectedRow = DataGridView1.SelectedRows(0).Cells("ID").Value.ToString()
    End If
End Sub
Run Code Online (Sandbox Code Playgroud)

我使用了与 David Hall 相同的事件,但没有使用BindingSource. 所以我遍历网格的所有行以找到之前选择的行。

Private Sub DataGridView1_Sorted() Handles DataGridView1.Sorted
    DataGridView1.ClearSelection()
    For Each xRow As DataGridViewRow In DataGridView1.Rows
        If xRow.Cells("ID").Value = cSelectedRow Then
            DataGridView1.CurrentCell = xRow.Cells(0)
            'Line Found. No need to loop through the rest.
            Exit For
        End If
    Next
End Sub
Run Code Online (Sandbox Code Playgroud)