在WinForm应用程序C#4.0中,我有一个绑定到SortableBindingList的DataGridView。因此,可以通过单击标题列进行排序 - 到目前为止一切正常; - )
问题是,所选行似乎被行号“记住”。以下是发生的事情:
A* <- "Selected"
B
C
现在排序降序,C在顶部并选中。我想要选择A:
C* <- "Selected"
B
A <- "Want have"
类似地,选择了多行。有解决方法吗?
答案 0 :(得分:11)
您可以通过在排序之前存储当前所选行(或行)的值然后重新选择该行来解决此问题。
您需要使用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论坛上找到了以下post,答案使用了DataBindingComplete事件 - 我不是100%为什么他们发现必要,因为我的方法适用于我的所有测试,但是你可能会发现它是一个有用的参考。
答案 1 :(得分:4)
这是我在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
答案 2 :(得分:1)
在网格的三个状态之一中,我尝试了David Hall的回答,但对我没有用,所以我在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){}
}
}