Italian [B4A][RISOLTO] Come posso prendere i dati con ItemClick da CustomListView collegata a Database SQL

3uowiS

Active Member
Licensed User
Innanzi tutto grazie a tutti delle risposte! Siete stati molto gentili!

Stavo provando questa soluzione:
Sub EventNamexclv_ItemClick (Index As Int, Value As Object) Dim id As = Value End Sub

ma se metto il codice così nel log non succede niente...
B4X:
Private Sub EventNamexclv_ItemClick (Index As Int, Value As Object)
    Dim id As String = Value
    Log(id)
End Sub
se invece metto senza EventName nel log mi da 0 qualsiasi oggetto della lista tocchi...
B4X:
Private Sub xclv_ItemClick (Index As Int, Value As Object)
    Dim id As String = Value
    Log(id)
End Sub

Scusate, ma non ho mai usato EventName, va inizializzato da qualche parte o in qualche modo?

Grazie di nuovo a tutti!
 

3uowiS

Active Member
Licensed User
Innanzi tutto grazie a tutti delle risposte! Siete stati molto gentili!

Stavo provando questa soluzione:


ma se metto il codice così nel log non succede niente...
B4X:
Private Sub EventNamexclv_ItemClick (Index As Int, Value As Object)
    Dim id As String = Value
    Log(id)
End Sub
se invece metto senza EventName nel log mi da 0 qualsiasi oggetto della lista tocchi...
B4X:
Private Sub xclv_ItemClick (Index As Int, Value As Object)
    Dim id As String = Value
    Log(id)
End Sub

Scusate, ma non ho mai usato EventName, va inizializzato da qualche parte o in qualche modo?

Grazie di nuovo a tutti!

C'è nessuno che mi può dire qualcosa in più sull'EventName? Perché non me lo prende?
 

udg

Expert
Licensed User
Longtime User
Scusate, ma non ho mai usato EventName, va inizializzato da qualche parte o in qualche modo?
Esattamente. Quando nel Designer aggiungi la xCLV puoi vedere tra le Properties sia Name che EventName.
In partenza coincidono; per questo se la tua CLV si chiama xclv anche l'evento itemclick sarà preceduto da xclv (xclv_ItemClick). Se invece cambi la proprietà EventName e la modifichi in MioEvento, allora lo stesso ItemClick risponderà a MioEvento_ItemClick.
Il fatto di avere una sub denominata EventNamexclv_ItemClick nel codice quando Event Name è xclv o MioEvento (o altro), fa solo sì che quella sub non venga mai eseguita.

Per completezza, è utile poter ridenominare EventName perchè potresti volere lo stesso evento associato a più componenti. In quel caso faresti uso di Sender (nell'evento) per discriminare tra i vari componenti e, spesso anche della proprietà TAG (immagina i due tastini +/- per incrementare/decrementare un valore; potresti avere un unico evento per entrambi e lasciare al codice la funzione di aumentare o diminuire il valore; ovviamente nulla impedisce di avere due eventi distinti, ognuno specializzato nella sua funzione di incremento o decremento).
 
Last edited:

Sagenut

Expert
Licensed User
Longtime User
se invece metto senza EventName nel log mi da 0 qualsiasi oggetto della lista tocchi...
Ottieni sempre 0 perché hai usato
B4X:
xclv.Add(p,"")
Prova con
B4X:
xclv.Add(p,rs)
Io però non sono pratico di DB.
La sintassi giusta per il tuo ItemClick dovrebbe essere
B4X:
Private Sub xclv_ItemClick (Index As Int, Value As Object)
    Dim id As ResultSet = Value
    Log(id)
End Sub
perché, come ti ha scritto @udg, inizialmente EventName corrisponde sempre al nome della View...... E tu probabilmente non lo hai cambiato.
 
Last edited:

3uowiS

Active Member
Licensed User
Ottieni sempre 0 perché hai usato
B4X:
xclv.Add(p,"")
No, questo lo avevo inizialmente, adesso ho
B4X:
xclv.Add(p, rs.GetInt("ID") ) 'Id del Database
come mi aveva scritto @Filippo però il risultato mi da comunque zero invece dell'ID del database.
Non capisco dove sbaglio...
 

3uowiS

Active Member
Licensed User
Non capisco dove sbaglio...
Ok, ho capito dov'era l'errore e adesso funziona, prende l'ID che è perfetto per quello che devo fare. 🥳

L'unica cosa è che adesso ci mette una vita a visualizzare la lista perché sono più di 500 righe di database e per ognuna viene fuori questo Log prima di aprire la lista:

Panel size is unknown. Layout may not be loaded correctly.
Panel size is unknown. Layout may not be loaded correctly.
Panel size is unknown. Layout may not be loaded correctly.
Panel size is unknown. Layout may not be loaded correctly.
Panel size is unknown. Layout may not be loaded correctly.
Panel size is unknown. Layout may not be loaded correctly.
Panel size is unknown. Layout may not be loaded correctly.
Panel size is unknown. Layout may not be loaded correctly.
Panel size is unknown. Layout may not be loaded correctly.
Panel size is unknown. Layout may not be loaded correctly.
ecc...

Non so se la lentezza dipenda da questo ma prima di mettere l'ItemClick questi messaggi ripetuti me ne venivano fuori molti meno e faceva molto prima ad aprirsi.

@Filippo, @Sagenut, @udg, @LucaMs, @Star-Dust, chiedo a voi che mi avevate già risposto, avete qualche idea su come potrei rimediare?
Grazie in anticipo!
 

Sagenut

Expert
Licensed User
Longtime User
Non credo che il rallentamento sia dato dai
Panel Size Unknown
Posta il codice di come leggi i dati dal DB per inserirli nella CLV.
 

3uowiS

Active Member
Licensed User
Io farei come allegato.
wow! Grazie mille @LucaMs! Mi hai fatto addirittura il file d'esempio... c'è solo un problema: per me è arabo quello che hai fatto! 😅
Spero di riuscire a capirci quanto basta per adattarlo all'app che sto creando! Grazie mille di nuovo per il tempo che gli hai dedicato, te ne sono molto grato!
 

3uowiS

Active Member
Licensed User
Non credo che il rallentamento sia dato dai
Panel Size Unknown
Posta il codice di come leggi i dati dal DB per inserirli nella CLV.

@Sagenut, stamani non so li motivo ma va molto più veloce...in circa 6 secondi apre il database quando l'altro giorno ce ne metteva 40/50... 6 secondi è accettabile credo.
Comunque in Activity Create ho questo codice:
B4X:
'Scelgo quali dati voglio prendere dal Player DB
    rs = Starter.sqlPlayers.ExecQuery("SELECT ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS ORDER BY GEN DESC")
    
    fill_clv (rs)

    rs.Close

In alto poi ho una barra di ricerca rapida che filtra in base a nome o altri valori:

B4X:
Private Sub edtSearchName_TextChanged (Old As String, New As String)
    Dim rs As ResultSet
    rs = Starter.sqlPlayers.ExecQuery2("SELECT ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS where PlayerName like ? ORDER BY GEN DESC", Array As String($"%${ New }%"$))
    fill_clv (rs)
    rs.Close
End Sub

Private Sub edtSearchGen_TextChanged (Old As String, New As String)
    Dim rs As ResultSet
    rs = Starter.sqlPlayers.ExecQuery2("SELECT ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE GEN like ? ", Array As String($"${ New }"$))
    fill_clv (rs)
    rs.Close
    If New = "" Then
        rs = Starter.sqlPlayers.ExecQuery("SELECT ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS ORDER BY GEN DESC")
        fill_clv (rs)
        rs.Close
    End If
End Sub

Private Sub spnTeam_ItemClick (Position As Int, Value As Object)
    Dim rs As ResultSet
    rs = Starter.sqlPlayers.ExecQuery2("SELECT ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Team like ? ORDER BY GEN DESC", Array As String($"${ Value }"$))
    If Position = 0 Then
        rs = Starter.sqlPlayers.ExecQuery("SELECT ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS ORDER BY GEN DESC")
    End If
    fill_clv (rs)
    rs.Close
End Sub

Private Sub cbxG_CheckedChange(Checked As Boolean)
    Dim rs As ResultSet
    If cbxG.Checked=True And cbxF.Checked=True And cbxC.Checked=True Then
        rs = Starter.sqlPlayers.ExecQuery("SELECT ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS ORDER BY GEN DESC")
        
    Else If cbxG.Checked=True And cbxF.Checked=True And cbxC.Checked=False Then
        rs = Starter.sqlPlayers.ExecQuery("Select ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Pos1='G' OR Pos2='G' Or Pos1='F' OR Pos2='F' ORDER BY GEN DESC")
    Else If cbxG.Checked=True And cbxF.Checked=False And cbxC.Checked=True Then
        rs = Starter.sqlPlayers.ExecQuery("Select ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Pos1='G' OR Pos2='G' Or Pos1='C' OR Pos2='C' ORDER BY GEN DESC")
    Else If cbxG.Checked=False And cbxF.Checked=True And cbxC.Checked=True Then
        rs = Starter.sqlPlayers.ExecQuery("Select ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Pos1='F' OR Pos2='F' Or Pos1='C' OR Pos2='C' ORDER BY GEN DESC")
        
    Else If cbxG.Checked=True And cbxF.Checked=False And cbxC.Checked=False Then
        rs = Starter.sqlPlayers.ExecQuery("Select ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Pos1='G' OR Pos2='G' ORDER BY GEN DESC")
    Else If cbxG.Checked=False And cbxF.Checked=True And cbxC.Checked=False Then
        rs = Starter.sqlPlayers.ExecQuery("Select ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Pos1='F' OR Pos2='F' ORDER BY GEN DESC")
    Else If cbxG.Checked=False And cbxF.Checked=False And cbxC.Checked=True Then
        rs = Starter.sqlPlayers.ExecQuery("Select ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Pos1='C' OR Pos2='C' ORDER BY GEN DESC")
        
    Else
        rs = Starter.sqlPlayers.ExecQuery("SELECT ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS ORDER BY GEN DESC")
    End If
    fill_clv (rs)
    rs.Close
End Sub

Private Sub cbxF_CheckedChange(Checked As Boolean)
    Dim rs As ResultSet
    If cbxG.Checked=True And cbxF.Checked=True And cbxC.Checked=True Then
        rs = Starter.sqlPlayers.ExecQuery("SELECT ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS ORDER BY GEN DESC")
        
    Else If cbxG.Checked=True And cbxF.Checked=True And cbxC.Checked=False Then
        rs = Starter.sqlPlayers.ExecQuery("Select ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Pos1='G' OR Pos2='G' Or Pos1='F' OR Pos2='F' ORDER BY GEN DESC")
    Else If cbxG.Checked=True And cbxF.Checked=False And cbxC.Checked=True Then
        rs = Starter.sqlPlayers.ExecQuery("Select ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Pos1='G' OR Pos2='G' Or Pos1='C' OR Pos2='C' ORDER BY GEN DESC")
    Else If cbxG.Checked=False And cbxF.Checked=True And cbxC.Checked=True Then
        rs = Starter.sqlPlayers.ExecQuery("Select ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Pos1='F' OR Pos2='F' Or Pos1='C' OR Pos2='C' ORDER BY GEN DESC")
        
    Else If cbxG.Checked=True And cbxF.Checked=False And cbxC.Checked=False Then
        rs = Starter.sqlPlayers.ExecQuery("Select ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Pos1='G' OR Pos2='G' ORDER BY GEN DESC")
    Else If cbxG.Checked=False And cbxF.Checked=True And cbxC.Checked=False Then
        rs = Starter.sqlPlayers.ExecQuery("Select ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Pos1='F' OR Pos2='F' ORDER BY GEN DESC")
    Else If cbxG.Checked=False And cbxF.Checked=False And cbxC.Checked=True Then
        rs = Starter.sqlPlayers.ExecQuery("Select ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Pos1='C' OR Pos2='C' ORDER BY GEN DESC")
        
    Else
        rs = Starter.sqlPlayers.ExecQuery("SELECT ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS ORDER BY GEN DESC")
    End If
    fill_clv (rs)
    rs.Close
End Sub

Private Sub cbxC_CheckedChange(Checked As Boolean)
    Dim rs As ResultSet
    If cbxG.Checked=True And cbxF.Checked=True And cbxC.Checked=True Then
        rs = Starter.sqlPlayers.ExecQuery("SELECT ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS ORDER BY GEN DESC")
        
    Else If cbxG.Checked=True And cbxF.Checked=True And cbxC.Checked=False Then
        rs = Starter.sqlPlayers.ExecQuery("Select ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Pos1='G' OR Pos2='G' Or Pos1='F' OR Pos2='F' ORDER BY GEN DESC")
    Else If cbxG.Checked=True And cbxF.Checked=False And cbxC.Checked=True Then
        rs = Starter.sqlPlayers.ExecQuery("Select ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Pos1='G' OR Pos2='G' Or Pos1='C' OR Pos2='C' ORDER BY GEN DESC")
    Else If cbxG.Checked=False And cbxF.Checked=True And cbxC.Checked=True Then
        rs = Starter.sqlPlayers.ExecQuery("Select ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Pos1='F' OR Pos2='F' Or Pos1='C' OR Pos2='C' ORDER BY GEN DESC")
        
    Else If cbxG.Checked=True And cbxF.Checked=False And cbxC.Checked=False Then
        rs = Starter.sqlPlayers.ExecQuery("Select ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Pos1='G' OR Pos2='G' ORDER BY GEN DESC")
    Else If cbxG.Checked=False And cbxF.Checked=True And cbxC.Checked=False Then
        rs = Starter.sqlPlayers.ExecQuery("Select ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Pos1='F' OR Pos2='F' ORDER BY GEN DESC")
    Else If cbxG.Checked=False And cbxF.Checked=False And cbxC.Checked=True Then
        rs = Starter.sqlPlayers.ExecQuery("Select ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE Pos1='C' OR Pos2='C' ORDER BY GEN DESC")
        
    Else
        rs = Starter.sqlPlayers.ExecQuery("SELECT ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS ORDER BY GEN DESC")
    End If
    fill_clv (rs)
    rs.Close
End Sub



A proposito, una domanda: se in questa sub
B4X:
Private Sub edtSearchGen_TextChanged (Old As String, New As String)

    Dim rs As ResultSet

    rs = Starter.sqlPlayers.ExecQuery2("SELECT ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS WHERE GEN like ? ", Array As String($"${ New }"$))

    fill_clv (rs)

    rs.Close

    If New = "" Then

        rs = Starter.sqlPlayers.ExecQuery("SELECT ID, PlayerName, Pos1, Pos2, Team, GEN from PLAYERS ORDER BY GEN DESC")

        fill_clv (rs)

        rs.Close

    End If

End Sub
io volessi mettere che non mostra solo il numero esatto come adesso ma anche i numeri minori come devo fare la query? Perché il simbolo >= non funziona...
 

3uowiS

Active Member
Licensed User
B4X:
Sub EventNamexclv_ItemClick (Index As Int, Value As Object)
    Dim PlayerName As String = xclv.GetPanel(Index).GetView(0).Text
    Dim Pos1 As String = xclv.GetPanel(Index).GetView(1).Text
    Dim Pos2 As String = xclv.GetPanel(Index).GetView(2).Text
    Dim Team As String = xclv.GetPanel(Index).GetView(3).Text
    Dim GEN As String = xclv.GetPanel(Index).GetView(4).Text
End Sub
Dovrai usare l'EventName della tua CustomListView per ItemClick.
Nell'esempio i GetView, da 0 a 4, potrebbero essere differenti dal tuo Layout.
Puoi sapere il numero da usare guardando il TreeView nel tuo Layout:
la View più in alto è la 0 e poi via a scendere.
Ho ipotizzato che nel Layout ci siano solo quelle 5 Labels.
E l'assegnazione a delle stringhe è puramente per esempio.

@Sagenut ho provato questo modo che mi hai mostrato perché adesso oltre a prendere l'ID ho bisogno di elaborare i dati "Pos1", "Pos2", "Gen".
Ma crasha dicendo che la view non è inizializzata.
Cosa devo fare per inizializzarla?

Oppure in alternativa in base al ID che ottengo non posso prelevare gli altri dati con una query sql?

Grazie in anticipo se vorrai rispondermi.
 

Sagenut

Expert
Licensed User
Longtime User
Se puoi posta la tua Sub xclv_ItemClick.
In alternativa potresti rifare il parsing del RS nello stesso modo di quando popoli la CLV.
Non sappiamo a quale soluzione sei arrivato quindi è difficile capire come aiutarti. :)

*** OT ***
I tuoi messaggi arrivano con del ritardo perché prima devono essere verificati dal moderatore (dovresti vedere anche tu un messaggio che ti dice questo ogni volta che posti qualcosa).
Puoi eliminare questo problema facendo una donazione per lo sviluppo di B4A, in modo da diventare Licensed Member.
È solo un consiglio, eh. ;)
*** FINE OT ***
 

3uowiS

Active Member
Licensed User
@Sagenut hai ragione, questa è la sub, al momento è basilare.

B4X:
Private Sub xclv_ItemLongClick (Index As Int, Value As Object)
    
    id = Value
    Log(id)
    Roster_Register 'salvo l'ID su un file txt
    ToastMessageShow("Aggiunto al roster", True)

End Sub
Che fa riferimento a
B4X:
xclv.Add(p, rs.GetString("ID"))

Ma come dicevo in questa sub prima di salvare l'ID ho bisogno di fare dei conteggi in base a quello che si seleziona elaborando i dati "Pos1", "Pos2", "Gen", quindi come pensi che potrei fare a prelevarli?

In alternativa potresti rifare il parsing del RS nello stesso modo di quando popoli la CLV.
Cioè? Scusa l'ignoranza ma non so cosa sia il parsing del RS... 😅 Ho imparato qualcosa ma sono ancora ai piedi di una montagna... 😬

*** OT ***
Grazie per l'informazione, non lo sapevo e infatti mi chiedevo il perché dovessi sempre passare dalla moderazione, ma pensavo che fosse perché sono nuovo.
Ho appena provveduto, avevo già in mente di fare una donazione perché se ho qualche possibilità di sviluppare questo progetto lo devo a questo programma!
*** OT-2***
Ma voi a parte anni di esperienza (che vogliono dire tanto), come avete imparato tutte queste cose?
Io al momento ho fatto 2 corsi di B4A su Udemy che mi hanno dato le basi e insegnato come muovermi, ma partivo da zero e vedo che tante cose sono ancora arabo per me e non so se riuscirò da solo ad andare fino in fondo a questo progetto. Un corso sul linguaggio Basic potrebbe aiutare?
*** FINE OT ***
 

Sagenut

Expert
Licensed User
Longtime User
Lì però hai tolto le modifiche che ti davano l'errore di View non inizializzata?
Perché senza non possiamo sapere cosa hai provato.
 

Sagenut

Expert
Licensed User
Longtime User
Non so se è possibile farlo, però proverei modificando quando popoli la CLV con
B4X:
xclv.Add(p, rs)
La gestione del click
B4X:
Private Sub xclv_ItemLongClick (Index As Int, Value As Object)
    Dim rs as ResultSet = value
    id = rs.getstring("ID")
    Log(id)
    Roster_Register 'salvo l'ID su un file txt
    ToastMessageShow("Aggiunto al roster", True)

End Sub
Se funziona così poi puoi usare i vari Getstring per prendere tutti i tuoi valori.
Però non ho lavorato con i DB quindi quello che ti ho scritto potrebbe non funzionare.
 
Last edited:

Sagenut

Expert
Licensed User
Longtime User
La variabile id alla quale cerchi di assegnare il valore è una variabile globale definita prima?
Altrimenti l'errore potrebbe essere quello.
 

3uowiS

Active Member
Licensed User
Non so se è possibile farlo, però proverei modificando quando popoli la CLV con
B4X:
xclv.Add(p, rs)
La gestione del click
B4X:
Private Sub xclv_ItemLongClick (Index As Int, Value As Object)
    Dim rs as ResultSet = value
    id = rs.getstring("ID")
    Log(id)
    Roster_Register 'salvo l'ID su un file txt
    ToastMessageShow("Aggiunto al roster", True)

End Sub
Se funziona così poi puoi usare i vari Getstring per prendere tutti i tuoi valori.
Però non ho lavorato con i DB quindi quello che ti ho scritto potrebbe non funzionare.

Ho provato ma crasha purtroppo!
Mi da errore su questa riga: "id = rs.getstring("ID")" e questo è l'errore: "android.database.StaleDataException: Attempting to access a closed CursorWindow.Most probable cause: cursor is deactivated prior to calling this method."
Ti dice niente?


Lì però hai tolto le modifiche che ti davano l'errore di View non inizializzata?
Perché senza non possiamo sapere cosa hai provato.
Si, ma avevo solo inserito i codice che mi avevi dato
B4X:
Dim Pos1 As String = xclv.GetPanel(Index).GetView(3).Text
Dim Pos2 As String = xclv.GetPanel(Index).GetView(4).Text
Dim GEN As String = xclv.GetPanel(Index).GetView(5).Text


La variabile id alla quale cerchi di assegnare il valore è una variabile globale definita prima?
Altrimenti l'errore potrebbe essere quello.
Si, "Dim id As String" l'ho messa in Globals
Ma l'id lo prende, sono gli altri valori che non so come riuscire a prenderli.

Ho provato anche con una query presa in base all'ID ossia
B4X:
cur = Starter.sqlPlayers.ExecQuery("Select Gen, Pos1, Pos2 from PLAYERS WHERE ID='"& id & "'")
Log(cur.GetString("Pos1"))
Gen = rs.GetInt("Gen")
Pos1 = cur.GetString("Pos1")
Pos2 = cur.GetString("Pos2")
ma crasha anche così...
 

Sagenut

Expert
Licensed User
Longtime User
Attempting to access a closed CursorWindow.Most probable cause: cursor is deactivated prior to calling this method."
Credo sia perché è stato chiamato RS.close prima e quindi non sono più accessibili.
 
D

Deleted member 103

Guest
io penso che così dovrebbe funzionare.
B4X:
xclv.Add(p, rs.getstring("ID"))

Private Sub xclv_ItemLongClick (Index As Int, Value As Object)
    cur = Starter.sqlPlayers.ExecQuery("Select Gen, Pos1, Pos2 from PLAYERS WHERE ID='"& Value & "'")
    Log(cur.GetString("Pos1"))
    Gen = rs.GetInt("Gen")
    Pos1 = cur.GetString("Pos1")
    Pos2 = cur.GetString("Pos2")
End Sub
 
Top