Eu tenho um controle DataGridView no qual uso um filtro. Isso tudo funciona. Quando executo o código por meio de um trabalhador em segundo plano, uso os dados dessa grade para que o trabalhador atue. O trabalhador então atualiza a grade (por exemplo, como no número de registros encontrados no processo dele (ela?) fazer o trabalho).
Consegui funcionar muito bem, se eu passar o índice da grade e depender da grade permanecer estática.
Onde as coisas vão para o lado é se eu trocar o filtro. Assim, o índice da grade muda, mesmo a linha com a qual eu estava trabalhando pode nem existir na exibição filtrada.
Então, começo a procurar uma solução, até mesmo encontrei alguns artigos aqui ( Como obtenho o DataRow selecionado em um DataGridView? ) Que pensei que poderia me apontar na direção certa.
Quando o trabalhador relata seu progresso (dela), o DataRowView está lá para ser lido, mas não pode atualizar o ItemArray.
Aqui estão alguns trechos de código:
Private Sub bgw_PostProcess_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles bgw_PostProcess.ProgressChanged
Select Case e.ProgressPercentage
Case 0
'~~ This is the code that is failing. The value of e.UserState(5) does not
' get set to the Row.ItemArray. (In debugging, it has a value of 9).
'
' e.UserState(6) is the DataRowView that gets passed to the BackgroundWorker
' and in debugging is correctly passed and present.
'
e.UserState(6).Row.ItemArray(1) = e.UserState(5)
ts_Status.Text = "Reading thread (page " & e.UserState(0) & " of " & e.UserState(2) & ")"
End Select
End Sub
Mesmo que esta não seja a maneira correta de atualizar o DataViewGrid, preciso de uma maneira de atualizar o DataTable subjacente que está associado ao controle DataGridView.
Alguma ideia?
Comentários adicionados (por solicitação).
Se você não estiver familiarizado com os trabalhadores em segundo plano, permita-me explicar. O trabalhador em segundo plano é essencialmente um thread separado executado independentemente do executável principal. Ele pode chamar dois sublinks para o executável principal: ProgressChanged e RunWorkerCompleted.
Quando ProgressChanged é acionado, há argumentos de evento que podem ser passados do trabalhador para o executável principal. Esta é a variável "e". Ele contém um objeto passado de volta. Esse código funciona bem. Esse não é o problema. Para fins relevantes aqui. A matriz e.UserState é:
[5] the number I want to show back on the DataGridControl
[6] the DataViewGrid.CurrentRow.DataBoundItem
O DataViewGridControl.CurrentRow.DataBoundItem é definido por meio de um objeto Queue:
qItemCount.Enqueue({grid_Names.Rows(idx).Cells("Name").Value,
"https://www.mywebsite.com/" & grid_Names.Rows(idx).Cells("Link").Value,
grid_Names.CurrentRow.DataBoundItem,
0})
bgw_PostProcess.RunWorkerAsync()
Este código funciona e, conforme solicitado, estou postando.
E o trabalhador de segundo plano faz a chamada para relatar o progresso no sub DoWork:
worker.ReportProgress(iProcessType, {iPageCount, sName, iMaxPages, sThreadTitle, sThreadID, iThreadImageCount, drvGridRow})
drvGridRow foi desenfileirado anteriormente de qItemCount. Isso tudo funciona exatamente como deveria.
No entanto, colocando um ponto de interrupção do
e.UserState(6).Row.ItemArray(1) = e.UserState(5)
e verificando as variáveis na janela de comando, obtenho o que esperava.
>? e.UserState(6).Row.ItemArray
{Length=3}
(0): "Person Name"
(1): 0
(2): "show.php?9524231"
>? e.UserState(5)
13
Observe que ItemArray(1) é zero. Isso é esperado.
Agora, quando passo para a próxima linha e verifico novamente as variáveis, obtenho o mesmo resultado, embora um valor atribuído de 13 seja atribuído a ItemArray(1). Eu até tentei codificar um valor lá e ele não será atualizado. Não há erro de tempo de execução gerado, o VB apenas age como se a atribuição funcionasse.
De acordo com a Microsoft, essa atribuição deve funcionar. Consulte a propriedade DataRow.ItemArray