簡體   English   中英

在 WinForm 應用程序中對 DataGridView 進行排序時選擇的行

[英]Selected rows when sorting DataGridView in WinForm application

在 WinForm 應用程序 C# 4.0 中,我有一個綁定到 SortableBindingList 的 DataGridView。 因此,可以通過單擊標題列對其進行排序 - 到目前為止一切正常;-)

問題是,所選行似乎被行號“記住”了。 這是發生的事情:

A*  <- "Selected"
B
C

現在按降序排序,C 在頂部並被選中。 我想仍然選擇 A:

C*  <- "Selected"
B
A   <- "Want have"

選擇多行時也會發生同樣的情況。 有解決方法嗎?

您可以通過在排序之前存儲當前選定行(或多行)的值,然后在之后重新選擇該行來解決此問題。

您需要使用 CellMouseDown 事件 - 必須使用此事件,因為它是唯一在排序發生之前觸發的事件。 像 ColumnHeaderMouseClick 這樣的替代事件都太晚了。

在 CellMouseDown 事件處理程序中,檢查行索引是否為 -1 以確保選擇了標題。

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

我有一個類層次字段selected ,我使用來存儲所選擇的列的唯一標識符。 如果您沒有唯一的 id,那么您可以為此目的添加一列並將其隱藏。

然后在 DataGridView 的Sorted eventhandler 中,您可以使用網格綁定源的 .Find() 方法:

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

在對此進行調查時,我在 MSDN 論壇上發現了以下帖子,其中答案使用 DataBindingComplete 事件 - 我不是 100% 為什么他們認為這是必要的,因為我的方法適用於我的所有測試,但您可能會發現它是一個有用的參考。

這是我在 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

我使用了與 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

我嘗試了 David Hall 的答案,但對我的網格中排序操作的三種狀態之一沒有用,所以我在MyDataGridView.cs類中更改了一些MyDataGridView.cs ,如下所示:

public string SelectedValue { get; set; }
private bool headerFirstClick = true;
public bool HeaderWasClicked = false;

private void MyDataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
    {
    try
       {
            if (headerFirstClick) Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = SortOrder.None;
            if (Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection == SortOrder.None)
            {
                Columns[e.ColumnIndex].SortMode = DataGridViewColumnSortMode.Automatic;
                Sort(Columns[e.ColumnIndex], System.ComponentModel.ListSortDirection.Ascending);
                Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = SortOrder.Ascending;
            }
                else if (Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection == SortOrder.Ascending)
            {
                Columns[e.ColumnIndex].SortMode = DataGridViewColumnSortMode.Programmatic;
                ((BindingSource)DataSource).Sort = string.Empty;
                Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = SortOrder.None;
            }
            headerFirstClick = false;
            int findValue = ((BindingSource)DataSource).Find(Columns[e.ColumnIndex].Name, SelectedValue);
            ((BindingSource)DataSource).Position = findValue;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
    }

protected override void OnCellClick(DataGridViewCellEventArgs e)
    {
        base.OnCellClick(e);
        if (e != null)
        {
            try
            {
                HeaderWasClicked = (e.RowIndex == -1);
                SelectedValue = SelectedRows[0].Cells[e.ColumnIndex].Value.ToString();
            }
            catch(Exception){}
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM