PDA

View Full Version : [VB.NET 2008]Ricerca Datagridview


Fabio7586
29-07-2009, 09:09
Salve, cerco aiuto circa una ricerca in una datagridview in tempo reale, senza pressione di pulsanti, io scrivo e automaticamente nel datagrid mi escono i risultati simultaneamente.

Private Sub txb_marca_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txb_marca.TextChanged
Dim dvfilter As DataView = Nothing
If TypeOf DGMAGAZ.DataSource Is DataView Then
dvfilter = CType(DGMAGAZ.DataSource, DataView)
ElseIf TypeOf DGMAGAZ.DataSource Is DataTable Then
dvfilter = CType(DGMAGAZ.DataSource, DataTable).DefaultView
End If
If txb_marca.TextLength > 0 Then
dvfilter.RowFilter = "MARCA like'" & txb_marca.Text & "*'"
Else
dvfilter.RowFilter = ""
End If
DGMAGAZ.DataSource = dvfilter
End Sub

Mi da un errore:
NullReferenceException non è stata Gestita
Riferimento a un oggetto non impostato su un'istanza di oggetto.

Premesso ciò, il codice su un altro progetto funziona perfettamente, le uniche cose che ho cambiato sono il nome della datagridview e della textbox.

Ringrazio per il tempo!

MarcoGG
29-07-2009, 19:50
Mi da un errore:
NullReferenceException non è stata Gestita
Riferimento a un oggetto non impostato su un'istanza di oggetto.

Premesso ciò, il codice su un altro progetto funziona perfettamente, le uniche cose che ho cambiato sono il nome della datagridview e della textbox.


Ti da errore DOVE ? Quale riga ?
Se il codice l'hai già testato in altro progetto e funziona, mi sembra logico pensare che c'è un semplice errore di trascrizione / copiatura...

Fabio7586
29-07-2009, 23:10
Ti da errore DOVE ? Quale riga ?
Se il codice l'hai già testato in altro progetto e funziona, mi sembra logico pensare che c'è un semplice errore di trascrizione / copiatura...

Scusa, faccio sempre lo stesso errore -_-' tralascio l'informazione più importante;
La riga è questa:
dvfilter.RowFilter = "MARCA like'" & txb_marca.Text & "*'"
il codice è fatto con un copia incolla ed è questo:
Private Sub txtsearch_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtsearch.TextChanged
Dim dvfilter As DataView = Nothing
If TypeOf dgContacts.DataSource Is DataView Then
dvfilter = CType(dgContacts.DataSource, DataView)
ElseIf TypeOf dgContacts.DataSource Is DataTable Then
dvfilter = CType(dgContacts.DataSource, DataTable).DefaultView
End If
If txtsearch.TextLength > 0 Then
dvfilter.RowFilter = "firstname like'" & txtsearch.Text & "*'"
Else
dvfilter.RowFilter = ""
End If
dgContacts.DataSource = dvfilter
End Sub

astorcas
30-07-2009, 10:41
La riga è questa:
dvfilter.RowFilter = "MARCA like'" & txb_marca.Text & "*'"


Tra i due (dvfilter e txb_marca) uno è null, quindi dgContacts.DataSource è null oppure non è nè di tipo DataTable né DataVIew, in alternativa txb_marca è null (se per esempio chiami questo metodo prima di InitializeComponent()).

In quale dei due casi ti trovi? (o magari me ne è sfuggito qualcun altro :))

MarcoGG
30-07-2009, 11:18
Scusa, faccio sempre lo stesso errore -_-' tralascio l'informazione più importante;
La riga è questa:
dvfilter.RowFilter = "MARCA like'" & txb_marca.Text & "*'"
il codice è fatto con un copia incolla ed è questo:
Private Sub txtsearch_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtsearch.TextChanged
Dim dvfilter As DataView = Nothing
If TypeOf dgContacts.DataSource Is DataView Then
dvfilter = CType(dgContacts.DataSource, DataView)
ElseIf TypeOf dgContacts.DataSource Is DataTable Then
dvfilter = CType(dgContacts.DataSource, DataTable).DefaultView
End If
If txtsearch.TextLength > 0 Then
dvfilter.RowFilter = "firstname like'" & txtsearch.Text & "*'"
Else
dvfilter.RowFilter = ""
End If
dgContacts.DataSource = dvfilter
End Sub

In ogni caso la tua tecnica mi pare un po' contorta e prolissa per quel che deve fare... Tipicamente userei :

- Un DataSet : destinato a contenere i dati, indipendentemente dalla rappresentazione che se ne vuole dare, filtrata o meno.

- Un BindingSource : destinato a fare "da ponte" tra il DataGridView e il DataSet, e ad applicare filtri, ordinamenti e quant'altro.

Il BindingSource viene associato al DataSet, mentre il DGV al BS. DGV e DS in pratica "non si parlano" direttamente :

> Dichiarazione :
Private DS As New DataSet
Private BS As New BindingSource

> Popolo il DataSet / Eseguo il binding :
' Qui il codice che popola il DataSet ...
' ...
BS.DataSource = DS.Tables(0)
DGV.DataSource = BS

> Gestione della TextBox filtro :

Private Sub txt_filtro_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txt_filtro.TextChanged

If txt_filtro.TextLength > 0 Then
BS.Filter = String.Format("MARCA Like '" & txt_filtro.Text) & "*'"
Else
BS.Filter = String.Empty
End If

End Sub

Breve, leggibile e funzionale. ;)
Questo ti evita anche di fare tutta quella casistica con If - Else If, che molto probabilmente è all'origine del tuo problema...

Fabio7586
30-07-2009, 11:48
In ogni caso la tua tecnica mi pare un po' contorta e prolissa per quel che deve fare... Tipicamente userei :

- Un DataSet : destinato a contenere i dati, indipendentemente dalla rappresentazione che se ne vuole dare, filtrata o meno.

- Un BindingSource : destinato a fare "da ponte" tra il DataGridView e il DataSet, e ad applicare filtri, ordinamenti e quant'altro.

Il BindingSource viene associato al DataSet, mentre il DGV al BS. DGV e DS in pratica "non si parlano" direttamente :

> Dichiarazione :
Private DS As New DataSet
Private BS As New BindingSource

> Popolo il DataSet / Eseguo il binding :
' Qui il codice che popola il DataSet ...
' ...
BS.DataSource = DS.Tables(0)
DGV.DataSource = BS

> Gestione della TextBox filtro :

Private Sub txt_filtro_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txt_filtro.TextChanged

If txt_filtro.TextLength > 0 Then
BS.Filter = String.Format("MARCA Like '" & txt_filtro.Text) & "*'"
Else
BS.Filter = String.Empty
End If

End Sub

Breve, leggibile e funzionale. ;)
Questo ti evita anche di fare tutta quella casistica con If - Else If, che molto probabilmente è all'origine del tuo problema...

Perdonami, ma come popolo il dataset ed eseguo il binding?
Il codice è quello sottolineato in nero?
il codice è questo
Imports System
Imports System.Data
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Data.OleDb
Public Class frm_zoomma
Private ds As New DataSet
Dim BS As New BindingSource
Private Sub frm_zoomma_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'TODO: questa riga di codice carica i dati nella tabella 'PN_MASTERDataSet6.Magazzino'. È possibile spostarla o rimuoverla se necessario.
Me.MagazzinoTableAdapter.Fill(Me.PN_MASTERDataSet6.Magazzino)
End Sub
Private Sub txb_marca_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txb_marca.TextChanged
BS.DataSource = ds.Tables(0)
DGMAGAZ.DataSource = BS
If txb_marca.TextLength > 0 Then
BS.Filter = String.Format("MARCA Like '" & txb_marca.Text) & "*'"
Else
BS.Filter = String.Empty
End If
End Sub
Private Sub DGMAGAZ_CellContentDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DGMAGAZ.CellContentDoubleClick
Dim marca, modello, colore, proven, brand As String
Dim prezzo As Double
Try
marca = DGMAGAZ.SelectedCells(0).Value.ToString()
modello = DGMAGAZ.SelectedCells(1).Value.ToString()
proven = DGMAGAZ.SelectedCells(2).Value.ToString()
colore = DGMAGAZ.SelectedCells(3).Value.ToString()
prezzo = DGMAGAZ.SelectedCells(4).Value
brand = DGMAGAZ.SelectedCells(5).Value.ToString()
Me.Close()
frm_inpnmaster.txmarca.Text = marca
frm_inpnmaster.txmode.Text = modello
frm_inpnmaster.txreg.Text = proven
frm_inpnmaster.txcol.Text = colore
frm_inpnmaster.txb_prezz.Text = prezzo
frm_inpnmaster.txbrand.Text = brand
frm_inpnmaster.txb_art.Text = modello & " " & proven & " " & colore
Catch
MsgBox("Non è stato Selezionato Nulla! Selezionare un modello!", MsgBoxStyle.Critical, "Errore")
Finally
End Try
End Sub
End Class

MarcoGG
30-07-2009, 12:27
Esatto, il metodo .Fill dell'Adapter serve proprio allo scopo di popolare il DataSet.

Private ds As New DataSet
Private BS As New BindingSource

Ma il DataSet deve essere quello su cui vuoi lavorare. Nel tuo caso ds non serve, inoltre perchè usare due qualificatori d'accesso diversi a livello di Form ? Usa Private e basta. Se usi Dim a livello di Form in pratica equivale a un Private...

BS.DataSource = Me.PN_MASTERDataSet6.Magazzino
DGMAGAZ.DataSource = BS

Dovrebbe andare così, ma FUORI dal TextChanged della TextBox che fa da filtro. Nella TextBox filtro vanno solo le istruzioni di gestione del filtro stesso, come nel mio esempio. Inutile ripetere il binding ogni volta che l'utente scrive un carattere nella TextBox filtro. Si rinnova il binding semmai ad ogni modifica dei dati, ma questo dipende da come tu vuoi che funzioni la cosa.

Inoltre c'è da considerare un altro fatto importante da gestire, che puoi implementare più avanti, ossia specificare un tempo minimo di reazione del filtro : se l'utente scrive velocemente N caratteri nel filtro, è chiaro che non vuole, in questa fase, visualizzare ogni risultato intermedio, ma solo i dati filtrati alla fine della digitazione. Su un datagridview con qualche centinaio di righe l'effetto sarà abbastanza ininfluente, ma su migliaia e migliaia di record avrà il suo bel risparmio in tempi di esecuzione...

Fabio7586
30-07-2009, 14:40
Esatto, il metodo .Fill dell'Adapter serve proprio allo scopo di popolare il DataSet.

Private ds As New DataSet
Private BS As New BindingSource

Ma il DataSet deve essere quello su cui vuoi lavorare. Nel tuo caso ds non serve, inoltre perchè usare due qualificatori d'accesso diversi a livello di Form ? Usa Private e basta. Se usi Dim a livello di Form in pratica equivale a un Private...

BS.DataSource = Me.PN_MASTERDataSet6.Magazzino
DGMAGAZ.DataSource = BS

Dovrebbe andare così, ma FUORI dal TextChanged della TextBox che fa da filtro. Nella TextBox filtro vanno solo le istruzioni di gestione del filtro stesso, come nel mio esempio. Inutile ripetere il binding ogni volta che l'utente scrive un carattere nella TextBox filtro. Si rinnova il binding semmai ad ogni modifica dei dati, ma questo dipende da come tu vuoi che funzioni la cosa.

Inoltre c'è da considerare un altro fatto importante da gestire, che puoi implementare più avanti, ossia specificare un tempo minimo di reazione del filtro : se l'utente scrive velocemente N caratteri nel filtro, è chiaro che non vuole, in questa fase, visualizzare ogni risultato intermedio, ma solo i dati filtrati alla fine della digitazione. Su un datagridview con qualche centinaio di righe l'effetto sarà abbastanza ininfluente, ma su migliaia e migliaia di record avrà il suo bel risparmio in tempi di esecuzione...

Grazie di tutte le info che mi stai dando, mi servono a tanto, ma questo BS.DataSource = Me.PN_MASTERDataSet6.Magazzino
DGMAGAZ.DataSource = BS
mi hai fatto capire che è inutile ripetere sempre il binding, ma se lo metto fuori dal textchanged, non vede nè BS nè DGMAGAZ, mentre se sta all'interno il codice ora funziona perfettamente, perchè fa così?

Inoltre volendo farlo per due filtri?

MarcoGG
30-07-2009, 21:53
ma se lo metto fuori dal textchanged, non vede nè BS nè DGMAGAZ, mentre se sta all'interno il codice ora funziona perfettamente, perchè fa così?


Non ho provato il tuo codice, perchè troppo personalizzato ( inoltre, da quel che ho capito, non sono troppo d'accordo sulla tua tecnica ). Mi sono limitato ad esporre un mio esempio, che sta a te, se vuoi, ricondurre al tuo caso. Se lo metti fuori dal TextChanged funziona eccome, deve funzionare. Ti posto l'esempio completo, per farti capire cosa intendo. Prima di mischiare la tua soluzione con la mia, creati un progettino di prova con questa Form, e vedrai che il concetto funziona :

Public Class Form1

Private DS As New DataSet
Private BS As New BindingSource

Private Sub cmd_fill_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmd_fill.Click

DS.Tables.Clear()
DS.Tables.Add()
DS.Tables(0).Columns.Add("MARCA")

DS.Tables(0).Rows.Add()
DS.Tables(0).Rows(DS.Tables(0).Rows.Count - 1).Item("MARCA") = "Microsoft"

DS.Tables(0).Rows.Add()
DS.Tables(0).Rows(DS.Tables(0).Rows.Count - 1).Item("MARCA") = "Marco"

DS.Tables(0).Rows.Add()
DS.Tables(0).Rows(DS.Tables(0).Rows.Count - 1).Item("MARCA") = "Machimelafattofare"

DS.Tables(0).Rows.Add()
DS.Tables(0).Rows(DS.Tables(0).Rows.Count - 1).Item("MARCA") = "Marca1"

DS.Tables(0).Rows.Add()
DS.Tables(0).Rows(DS.Tables(0).Rows.Count - 1).Item("MARCA") = "Marca2"

BS.DataSource = DS.Tables(0)
DGV.DataSource = BS

End Sub

Private Sub txt_filtro_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txt_filtro.TextChanged

If txt_filtro.TextLength > 0 Then
Try
BS.Filter = "MARCA Like '" & txt_filtro.Text & "*'"
Catch ex As Exception
End Try
Else
BS.Filter = String.Empty
End If

End Sub

End Class

Nell'esempio non c'è nessun DB, nè Adapter, non servono, quello che conta è arrivare ad avere un DataSet popolato ( DS, che io popolo via codice tramite il pulsante "cmd_fill" ). Tutto ciò che serve sulla Form è :
- pulsante "cmd_fill".
- DataGridView "DGV".
- TextBox "txt_filtro".

Ho fatto una piccola modifica. Quello "String.Format" nel nostro caso è superfluo, inoltre ho aggiunto un Try Catch, prova a rimuoverlo e digita nella text filtro il carattere " ' ", e capirai perchè... ;)
Cmq, sta cosa la dovrai gestire in modo più elegante, impedendo l'input di caratteri indesiderati...


Inoltre volendo farlo per due filtri?


Due filtri in che senso ? 2 textbox su 2 campi, sullo stesso campo, ... ?

Fabio7586
31-07-2009, 13:12
Non ho provato il tuo codice, perchè troppo personalizzato ( inoltre, da quel che ho capito, non sono troppo d'accordo sulla tua tecnica ). Mi sono limitato ad esporre un mio esempio, che sta a te, se vuoi, ricondurre al tuo caso. Se lo metti fuori dal TextChanged funziona eccome, deve funzionare. Ti posto l'esempio completo, per farti capire cosa intendo. Prima di mischiare la tua soluzione con la mia, creati un progettino di prova con questa Form, e vedrai che il concetto funziona :

Public Class Form1

Private DS As New DataSet
Private BS As New BindingSource

Private Sub cmd_fill_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmd_fill.Click

DS.Tables.Clear()
DS.Tables.Add()
DS.Tables(0).Columns.Add("MARCA")

DS.Tables(0).Rows.Add()
DS.Tables(0).Rows(DS.Tables(0).Rows.Count - 1).Item("MARCA") = "Microsoft"

DS.Tables(0).Rows.Add()
DS.Tables(0).Rows(DS.Tables(0).Rows.Count - 1).Item("MARCA") = "Marco"

DS.Tables(0).Rows.Add()
DS.Tables(0).Rows(DS.Tables(0).Rows.Count - 1).Item("MARCA") = "Machimelafattofare"

DS.Tables(0).Rows.Add()
DS.Tables(0).Rows(DS.Tables(0).Rows.Count - 1).Item("MARCA") = "Marca1"

DS.Tables(0).Rows.Add()
DS.Tables(0).Rows(DS.Tables(0).Rows.Count - 1).Item("MARCA") = "Marca2"

BS.DataSource = DS.Tables(0)
DGV.DataSource = BS

End Sub

Private Sub txt_filtro_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txt_filtro.TextChanged

If txt_filtro.TextLength > 0 Then
Try
BS.Filter = "MARCA Like '" & txt_filtro.Text & "*'"
Catch ex As Exception
End Try
Else
BS.Filter = String.Empty
End If

End Sub

End Class

Nell'esempio non c'è nessun DB, nè Adapter, non servono, quello che conta è arrivare ad avere un DataSet popolato ( DS, che io popolo via codice tramite il pulsante "cmd_fill" ). Tutto ciò che serve sulla Form è :
- pulsante "cmd_fill".
- DataGridView "DGV".
- TextBox "txt_filtro".

Ho fatto una piccola modifica. Quello "String.Format" nel nostro caso è superfluo, inoltre ho aggiunto un Try Catch, prova a rimuoverlo e digita nella text filtro il carattere " ' ", e capirai perchè... ;)
Cmq, sta cosa la dovrai gestire in modo più elegante, impedendo l'input di caratteri indesiderati...



Due filtri in che senso ? 2 textbox su 2 campi, sullo stesso campo, ... ?

Io vb.net lo conosco in modo superficiale, ma è soprattutto grazie al tuo aiuto che sto approfondendo man mano questo linguaggio, anzi ti chiedo gentilmente se mi consigliassi qualche testo di ottima fattura da cui poter approfondire per bene la mia conoscenza!

Due filtri nel senso di due texbox MARCA e MODELLO, ho provato a replicare il codice, ma il risultato è un datagridview vuoto!

Grazie e scusa sempre per il disturbo! :)

MarcoGG
31-07-2009, 13:59
Due filtri nel senso di due texbox MARCA e MODELLO, ho provato a replicare il codice, ma il risultato è un datagridview vuoto!


Non è possibile... :D
Non so, per me è di una chiarezza totale. Prova semplicemente un progetto con questa Form :

Public Class Form1

Private DS As New DataSet
Private BS As New BindingSource
Private filtroMarca As String = String.Empty
Private filtroMod As String = String.Empty

Private Sub cmd_fill_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmd_fill.Click

DS.Tables.Clear()
DS.Tables.Add()

DS.Tables(0).Columns.Add("MARCA")
DS.Tables(0).Columns.Add("MODELLO")

DS.Tables(0).Rows.Add()
DS.Tables(0).Rows(DS.Tables(0).Rows.Count - 1).Item("MARCA") = "AAB"
DS.Tables(0).Rows(DS.Tables(0).Rows.Count - 1).Item("MODELLO") = "m1A"

DS.Tables(0).Rows.Add()
DS.Tables(0).Rows(DS.Tables(0).Rows.Count - 1).Item("MARCA") = "AAC"
DS.Tables(0).Rows(DS.Tables(0).Rows.Count - 1).Item("MODELLO") = "m2A"

DS.Tables(0).Rows.Add()
DS.Tables(0).Rows(DS.Tables(0).Rows.Count - 1).Item("MARCA") = "ABB"
DS.Tables(0).Rows(DS.Tables(0).Rows.Count - 1).Item("MODELLO") = "m1B"

DS.Tables(0).Rows.Add()
DS.Tables(0).Rows(DS.Tables(0).Rows.Count - 1).Item("MARCA") = "ABC"
DS.Tables(0).Rows(DS.Tables(0).Rows.Count - 1).Item("MODELLO") = "m2B"

BS.DataSource = DS.Tables(0)
DGV.DataSource = BS

End Sub

Private Sub txt_marca_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txt_marca.TextChanged, txt_modello.TextChanged

If txt_marca.TextLength > 0 Then
filtroMarca = "MARCA Like '" & txt_marca.Text & "*'"
Else
filtroMarca = "MARCA Like '*'"
End If

If txt_modello.TextLength > 0 Then
filtroMod = "MODELLO Like '" & txt_modello.Text & "*'"
Else
filtroMod = "MODELLO Like '*'"
End If

BS.Filter = filtroMarca & " AND " & filtroMod

End Sub

End Class

C'è già il doppio filtro su Marca / Modello.
Prova, e non dirmi che non funziona ! :D

Fabio7586
01-08-2009, 14:22
Scusa, ma non avevo idea che potevo scatenare due eventi textchange conteporaneamente. Conoscendo solo il pascal a livello scolastico ( che comunque ho fatto 7 o 8 anni fa), mi risulta difficile capire le cose, per questo ti chiedo aiuto, tant'è vero che tutte le cose che so, me le hai insegnate tu, ed è per questo anche che ti ho chiesto, se ne conosci qualcuno, un buon libro su vb.net.
Non essere troppo severo :), in ogni caso ti sono grato per l'aiuto ed il tempo che mi concedi!
Ciao e grazie!

MarcoGG
01-08-2009, 19:31
Scusa, ma non avevo idea che potevo scatenare due eventi textchange conteporaneamente. Conoscendo solo il pascal a livello scolastico ( che comunque ho fatto 7 o 8 anni fa), mi risulta difficile capire le cose, per questo ti chiedo aiuto, tant'è vero che tutte le cose che so, me le hai insegnate tu, ed è per questo anche che ti ho chiesto, se ne conosci qualcuno, un buon libro su vb.net.
Non essere troppo severo :), in ogni caso ti sono grato per l'aiuto ed il tempo che mi concedi!
Ciao e grazie!

Mannò, macchè severo. :D

Esatto, la clausola Handles permette questa "scorciatoia" senza bisogno di dover riscrivere N volte la stessa routine. Un'altra alternativa è mettere la routine del filtro in una Private Sub, e semplicemente richiamarla da ogni TextBox-filtro presente sulla Form : in presenza di molte TextBox-filtro è forse anche preferibile, invece che aggiungere una lunga lista di Controllo.Evento nell'Handles. ;)

Per i manuali, quelli base che consiglio son sempre quelli, i due di Balena, vedi qui, al mio post #24 :
http://www.hwupgrade.it/forum/showthread.php?t=2019296&page=2

Ottimi per il linguaggio e il framework, ma non tanto utili se il tuo scopo è soprattutto approfondire ADO.NET in ambiente WinForms. In ogni caso un'ottima base, se vuoi conoscere meglio VB.

Fabio7586
25-08-2009, 18:18
ciao, riuppo questo post per non crearne uno nuovo giacchè ho effettuato una modifica e non riesco più a raccapezzarmi;
Prima avevo un dataset (creavo una connessione con procedura guidata) che filtravo;Ho dovuto Modificare perchè non riuscivo ad aggiornare il dataset con delle nuove modifiche che avevo effettuato al dataset e così ho deciso di caricarlo manualmente il datagridview così:
Private Sub frm_zoomma_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim ConnString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & Application.StartupPath & "\PN_MASTER.accdb;Persist Security Info=False;"
Dim Cn As New OleDbConnection(ConnString)
Dim sql As String = "select * from Magazzino"
Dim cmd As New OleDbCommand(sql, Cn)
Dim righe As Integer
'Apro la connessione
If (Cn.State) = ConnectionState.Closed Then
Cn.Open()
End If
Dim RDR As OleDb.OleDbDataReader = cmd.ExecuteReader()
While (RDR.Read())
Dim nuovaRow As New DataGridViewRow
nuovaRow.CreateCells(DGMAGAZ)
nuovaRow.Cells(0).Value = RDR("CONTATORE")
nuovaRow.Cells(1).Value = RDR("MARCA")
nuovaRow.Cells(2).Value = RDR("MODELLO")
nuovaRow.Cells(3).Value = RDR("REGIONE")
nuovaRow.Cells(4).Value = RDR("COLORE")
nuovaRow.Cells(5).Value = RDR("PREZZO")
nuovaRow.Cells(6).Value = RDR("BRAND")
DGMAGAZ.Rows.Add(nuovaRow)
End While
End Sub
Private Sub txb_marca_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txb_marca.TextChanged, txb_modello.TextChanged
BS.DataSource = DGMAGAZ
DGMAGAZ.DataSource = BS
If txb_marca.TextLength > 0 Then
filtroMarca = "MARCA Like '" & txb_marca.Text & "*'"
Else
filtroMarca = "MARCA Like '*'"
End If

If txb_modello.TextLength > 0 Then
filtroMod = "MODELLO Like '" & txb_modello.Text & "*'"
Else
filtroMod = "MODELLO Like '*'"
End If

BS.Filter = filtroMarca & " AND " & filtroMod
End Sub

ora però il filtro restituisce sempre righe vuote!
Come faccio a ripristinare il filtro?
Grazie e scusate il disturbo!

MarcoGG
27-08-2009, 09:49
Se carichi il DGV manualmente non esegui più il binding, quindi è ovvio che vai a "spezzare la catena" tra DGV, DS, BS. A quel punto i filtri non funzionano più. Il metodo .CreateCells(DGMAGAZ) serve solo a creare un record già conforme al DGV, ma non è un'operazione di binding.
Dovresti abbandonare quel sistema, e cercare di risolvere il problema a monte sul dataset, che hai accennato...

christiantric
02-09-2009, 15:43
Inoltre c'è da considerare un altro fatto importante da gestire, che puoi implementare più avanti, ossia specificare un tempo minimo di reazione del filtro : se l'utente scrive velocemente N caratteri nel filtro, è chiaro che non vuole, in questa fase, visualizzare ogni risultato intermedio, ma solo i dati filtrati alla fine della digitazione. Su un datagridview con qualche centinaio di righe l'effetto sarà abbastanza ininfluente, ma su migliaia e migliaia di record avrà il suo bel risparmio in tempi di esecuzione...

Ciao Marco,
mi appiglio a questo stralcio di post perchè mi fa pensare che tu sappia come fare...devo specificare un tempo di reazione del filtro...come posso fare? Non riesco a vedere nessuna proprietà utile nel BindingSource.

MarcoGG
03-09-2009, 08:41
Ciao Marco,
mi appiglio a questo stralcio di post perchè mi fa pensare che tu sappia come fare...devo specificare un tempo di reazione del filtro...come posso fare? Non riesco a vedere nessuna proprietà utile nel BindingSource.

Semplicemente puoi aggiungere alla Form un Timer "tmr_filtro" con Enabled a False. Attenzione a scegliere l'Interval con un valore opportuno ( inizierei con un 200 msec. ).
A questo punto spostiamo la gestione dei filtri dal _TextChanged al _Tick del timer, mentre un inserimento nella textbox filtro non farà altro che arrestare e riavviare il timer :

Private Sub txt_marca_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txt_marca.TextChanged, txt_modello.TextChanged

tmr_filtro.Enabled = False
tmr_filtro.Enabled = True

End Sub

Private Sub tmr_filtro_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmr_filtro.Tick

If txt_marca.TextLength > 0 Then
filtroMarca = "MARCA Like '" & txt_marca.Text & "*'"
Else
filtroMarca = "MARCA Like '*'"
End If

If txt_modello.TextLength > 0 Then
filtroMod = "MODELLO Like '" & txt_modello.Text & "*'"
Else
filtroMod = "MODELLO Like '*'"
End If
BS.Filter = filtroMarca & " AND " & filtroMod

ListBox1.Items.Add("filtro applicato")
tmr_filtro.Enabled = False

End Sub

e il gioco è fatto. ;)
[ ListBox1 è a scopo di debug, e rende un'idea precisa del funzionamento... ]

christiantric
03-09-2009, 09:59
Semplicemente puoi aggiungere alla Form un Timer "tmr_filtro" con Enabled a False. Attenzione a scegliere l'Interval con un valore opportuno ( inizierei con un 200 msec. ).
A questo punto spostiamo la gestione dei filtri dal _TextChanged al _Tick del timer, mentre un inserimento nella textbox filtro non farà altro che arrestare e riavviare il timer :

Private Sub txt_marca_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txt_marca.TextChanged, txt_modello.TextChanged

tmr_filtro.Enabled = False
tmr_filtro.Enabled = True

End Sub

Private Sub tmr_filtro_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmr_filtro.Tick

If txt_marca.TextLength > 0 Then
filtroMarca = "MARCA Like '" & txt_marca.Text & "*'"
Else
filtroMarca = "MARCA Like '*'"
End If

If txt_modello.TextLength > 0 Then
filtroMod = "MODELLO Like '" & txt_modello.Text & "*'"
Else
filtroMod = "MODELLO Like '*'"
End If
BS.Filter = filtroMarca & " AND " & filtroMod

ListBox1.Items.Add("filtro applicato")
tmr_filtro.Enabled = False

End Sub

e il gioco è fatto. ;)
[ ListBox1 è a scopo di debug, e rende un'idea precisa del funzionamento... ]

Grazie Marco,
molto chiaro ed esplicativo.

Ignoravo completamente la presenza del controllo Timer...appena posso implemento la soluzione e ti faccio sapere.