+ Rispondi al Thread
Visualizzazione dei risultati da 1 a 4 su 4

Discussione: [VB.net 2015 E] - Flowlayout panel e selezione sequenziale degli items visibili.

  1. #1
    Dev-01 non è in linea Scolaretto
    Post
    403

    [VB.net 2015 E] - Flowlayout panel e selezione sequenziale degli items visibili.

    Buonasera,

    Ho implementato un controllo personalizzato simile ad una listbox basandomi su un flowlayoutpanel al quale aggiungo dei controlli per comodità espositiva assimilabili a delle linee.

    Quando tutte le linee sono visibili riesco a navigare fra esse modificando la selezione col seguente codice:

    codice:
      Public Sub Navigate(ByVal Forward As Boolean)
    
            Dim VisibleItems As Integer
            Dim CurrentIndex As Integer
    
           ' * Il ciclo è scritto per comodità espositiva, nella realtà si tiene traccia di CurrentIndex 
           '    in una apposita proprietà: rappresenta la selezione corrente.
    
            For x As Integer = 0 To List.Controls.Count - 1
                If List.Controls(x).Visible Then
                    VisibleItems += 1
                    If TypeOf (List.Controls(x)) Is Line Then
                        Dim L As Line = List.Controls(x)
                        If L.Selected Then
                            CurrentIndex = x + 1
                        End If
                    End If
                End If
            Next
    
            If VisibleItems = 0 Then Exit Sub
    
            ' * Credo che il problema risieda nella sezione di codice che segue.
            If Forward = False Then
                If CurrentIndex - 1 < 1 Then
                    CurrentIndex = VisibleItems
                Else
                    CurrentIndex -= 1 ' * Qui.
                End If
            Else
                If CurrentIndex + 1 > VisibleItems Then
                    CurrentIndex = 1
                Else
                    CurrentIndex += 1 ' * E qui.
                End If
            End If
            ' * Fine sezione incriminabile
    
            Dim ComparisonIndex As Integer
    
            For x As Integer = 0 To List.Controls.Count - 1
                ComparisonIndex += 1
    
                If TypeOf (List.Controls(x)) Is Line Then
                    Dim L As Line = List.Controls(x)
    
                    If ComparisonIndex = CurrentIndex Then
                        L.Selected = True
                    Else
                        L.Selected = False
                    End If
                End If
            Next
    
        End Sub
    Il controllo espone un'altra routine che esemplifica graficamente la ricerca nelle linee impostandone la proprietà '.Visible' a 'False' qualora la proprietà '.Text' non contenga un frammento di stringa digitato in una casella di testo dall'utente.

    Il mio problema è che non riesco a saltare correttamente le linee non visibili per passare alla selezione della prima linea successiva o precedente alla selezione corrente.

    Ricapitolando:

    Ho un flowlayoutpanel contenente dei controlli navigabili tramite tasti freccia;
    Ho una routine che mi consente di visualizzare solo i controlli la cui proprietà '.Text' contiene una arbitraria porzione di testo;
    Ho bisogno di navigare correttamente nella successione saltando i controlli non visibili.

    Grazie a chi vorrà aiutarmi.

  2. #2
    L'avatar di Max.Riservo
    Max.Riservo non è in linea Scribacchino
    Post
    550
    Ciao Dev,
    l'errore è esattamente dove pensi tu.
    Tu scorri un insieme di composto da p.e. 100 elementi, di cui 50 visibili (VisibleItems) e poi ti posizioni sull'ultimo visibile (CurrentIndex) .. i.e. nella pos. 96.
    Poi per muoverti in avanti o indietro ti accontenti di sommare / sottrarre 1 al CurrentIndex ..... e chi ti garantisce che così facendo la nuova posizione si riferisca ad un elemento visibile ?

    Tu devi cercare il primo visibile in avanti o indietro .... almeno io farei così.

    Notte

  3. #3
    Dev-01 non è in linea Scolaretto
    Post
    403
    Ciao Max e grazie per la risposta.
    In realtà la prima versione del codice prevedeva un Do While Not ... Loop per posizionarsi sul primo elemento visibile ma non so per quale motivo non riuscivo ad ottenere il risultato voluto.

    La sezione proposta vuole essere in qualche modo esemplificativa e rappresentativa del problema: avendo scritto varie versioni della routine non potevo postarle tutte.

  4. #4
    Dev-01 non è in linea Scolaretto
    Post
    403
    Posto la soluzione:

    Mi sono appoggiato ad una funzione esterna che richiama se stessa in modo ricorsivo qualora tra le voci visibili non risulti quella con indice generale pari a 0 ma si superi il totale degli items totali disponibili nella lista:

    La porzione di codice:

    codice:
    If Forward Then
               CurrentIndex = GetNextVisibleItemIndex(CurrentIndex)
                 
                For x As Integer = 0 To List.Controls.Count - 1
    
                    If TypeOf (List.Controls(x)) Is Line Then
                        Dim L As Line = List.Controls(x)
    
                        If x = CurrentIndex Then
                            L.Selected = True
                        Else
                            L.Selected = False
                        End If
                    End If
                Next
    
    End If
    La funzione esterna realizzata per procedere dalla selezione corrente in avanti:

    codice:
     Function GetNextVisibleItemIndex(ByVal CurrentIndex As Integer) As Integer
    
            For x As Integer = CurrentIndex To List.Controls.Count - 1
                If List.Controls(x).Visible Then Return x
            Next
    
            Return GetNextVisibleItemIndex(0)
    End Function
    Come si può notare la funzione GetNextVisibleItemIndex promette la "circolarità" della ricerca: indipendentemente dall'indice del primo elemento visibile, qualora si superi la lunghezza della lista, riparte daccapo assicurando la selezione corretta.

    Con una piccola modifica alla funzione si può procedere anche in senso inverso in modo da selezionare l'elemento precedente a quello corrente ripartendo dall'ultimo elemento della lista qualora l'indice risulti inferiore a zero.

    Nota:

    Grazie Max: ho trovato la soluzione riflettendo sulle tue parole negli ultimi due giorni in uno dei rari istanti di lucidità.
    Sei una delle mie informatiche colonne!
    Ultima modifica di Dev-01; 14-03-2018 16:52 

+ Rispondi al Thread

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi