2011-01-27 1 views
10

In un'applicazione WinForm, C# 4.0, ho un DataGridView associato a un SortableBindingList. Quindi può essere ordinato facendo clic sulla colonna dell'intestazione - tutto bene finora ;-)Righe selezionate durante l'ordinamento di DataGridView nell'applicazione WinForm

Il problema è che le righe selezionate sembrano essere "ricordate" dal numero di riga. Ecco cosa succede:

A* <- "Selected" 
B 
C 

Ora ordinamento discendente, C in alto e selezionato. Mi piacerebbe avere A selezionato:

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

Lo stesso succede con più file selezionate. C'è una soluzione per questo?

+0

Sei corretto. Le righe selezionate vengono "ricordate" dall'indice di riga e non dai valori di riga. –

+0

ASP .NET 4 ha introdotto la proprietà EnablePersistedSelection per GridView. Ma non sembra che sia disponibile per WinForms. http://www.asp.net/learn/whitepapers/aspnet4#0.2__Toc253429262 –

risposta

11

È possibile aggirare questo comportamento memorizzando il valore della riga (o delle righe) attualmente selezionata prima di ordinare e quindi riselezionare la riga in seguito.

È necessario utilizzare l'evento CellMouseDown: è necessario utilizzare questo evento poiché è l'unico che viene attivato prima che avvenga l'ordinamento. Eventi alternativi come ColumnHeaderMouseClick sono fin troppo tardi.

Nel gestore di eventi CellMouseDown controllare che l'indice di riga sia -1 per garantire che le intestazioni siano state selezionate.

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

Ho un campo livello di classe selected che uso per memorizzare l'identificatore univoco della colonna selezionata. Se non si dispone di un ID univoco, è possibile aggiungere una colonna per questo scopo e nasconderlo.

Poi nel Sorted EventHandler della DataGridView è possibile utilizzare il metodo .find() della fonte vincolante della griglia:

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

Mentre indaga questo ho trovato la seguente post sui forum MSDN Qualora le applicazioni di risposta l'evento DataBindingComplete: non sono al 100% il motivo per cui l'hanno trovato necessario in quanto il mio approccio ha funzionato per tutti i miei test, ma potresti trovarlo un utile riferimento.

3

Ecco il mio approccio in 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 

ho usato gli stessi eventi come David Hall, ma non ho usato la BindingSource. Quindi collego tutte le linee della griglia per trovare quella che è stata selezionata in precedenza.

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