Editar SubItems de un listview en VB.NET

Iniciado por bybaal, 8 Enero 2016, 17:28 PM

0 Miembros y 1 Visitante están viendo este tema.

bybaal

Hola a todos, quisiera saber como permitir a los usuarios editar los subitems de un listview, ya que con la propiedad LabelEdit sólo se pueden editar los items, aquí les dejo un ejemplo para que se vea mejor

Código (vbnet) [Seleccionar]

   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
       Dim C As Integer

       ListView1.View = View.Details
       ListView1.Columns.Add("Items")
       ListView1.Columns.Add("SubItems", 70)
       ListView1.FullRowSelect = True
       ListView1.GridLines = True
       'A pesar que permito modificar los items,
       'no me lo permite para los subitems, que es lo que quiero hacer.
       ListView1.LabelEdit = True

       For C = 0 To 20
           ListView1.Items.Add("Prueba " & C)
           ListView1.Items(C).SubItems.Add("SubItem " & C)
       Next
   End Sub

Eleкtro

#1
Esa es una limitación del control ListView, por lo tanto es algo que debes implementar por ti mismo.

Te he escrito el siguiente ejemplo funcional (para editar una celda o subitem haz doble-click):
Código (vbnet) [Seleccionar]
   Friend WithEvents TextBoxLvItem As TextBox
   Private currentItem As ListViewSubItem

   Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

       Me.TextBoxLvItem = New TextBox With {.Visible = False}
       Me.Controls.Add(Me.TextBoxLvItem)

   End Sub

   Private Sub ListView1_MouseClick(ByVal sender As Object, ByVal e As MouseEventArgs) _
   Handles ListView1.MouseClick

       Me.TextBoxLvItem.Hide()

   End Sub

   Private Sub ListView1_MouseDoubleClick(ByVal sender As Object, ByVal e As MouseEventArgs) _
   Handles ListView1.MouseDoubleClick

       Dim lv As ListView = DirectCast(sender, ListView)
       Dim hitTest As ListViewHitTestInfo = lv.HitTest(e.X, e.Y)
       Me.currentItem = hitTest.SubItem

       With Me.TextBoxLvItem
           .Width = lv.Columns(hitTest.Item.Index).Width
           .Left = (lv.Left + hitTest.SubItem.Bounds.Left + 3)
           .Top = (lv.Top + hitTest.SubItem.Bounds.Top)
           .Text = hitTest.SubItem.Text
           .Show()
           .Focus()
           .SelectAll()
       End With

       lv.SendToBack()

   End Sub

   Private Sub TextBoxLvItem_KeyUp(ByVal sender As Object, ByVal e As KeyEventArgs) _
   Handles TextBoxLvItem.KeyUp

       Select Case e.KeyData

           Case Keys.Return ' Guardar el texto.
               currentItem.Text = DirectCast(sender, TextBox).Text
               DirectCast(sender, TextBox).Hide()

           Case Keys.Escape ' No guardar el texto.
               DirectCast(sender, TextBox).Hide()

           Case Else
               '...

       End Select

   End Sub


PD: No actives el LabelEdit, no es necesario con el código que mostré.

Saludos








bybaal

Tengo en el listview dos columnas y 20 items, cada item tiene un subitem. Cuando el index del elemento es menor o igual que el index de la última columna funciona bien, pero cuando el el index del elemento es mayor que el index de la última columna, ejemplo: doy docble clic en un item o subitem de index >=3 da el siguiente error:

Código (vbnet) [Seleccionar]

'InvalidArgument=El valor de '4' no es válido para 'index'.
'Nombre del parámetro: index
.Width = lv.Columns(hitTest.Item.Index).Width


Cita de: Eleкtro en  8 Enero 2016, 19:16 PM
Esa es una limitación del control ListView, por lo tanto es algo que debes implementar por ti mismo.

Te he escrito el siguiente ejemplo funcional (para editar una celda o subitem haz doble-click):
Código (vbnet) [Seleccionar]
   Friend WithEvents TextBoxLvItem As TextBox
   Private currentItem As ListViewSubItem

   Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

       Me.TextBoxLvItem = New TextBox With {.Visible = False}
       Me.Controls.Add(Me.TextBoxLvItem)

   End Sub

   Private Sub ListView1_MouseClick(ByVal sender As Object, ByVal e As MouseEventArgs) _
   Handles ListView1.MouseClick

       Me.TextBoxLvItem.Hide()

   End Sub

   Private Sub ListView1_MouseDoubleClick(ByVal sender As Object, ByVal e As MouseEventArgs) _
   Handles ListView1.MouseDoubleClick

       Dim lv As ListView = DirectCast(sender, ListView)
       Dim hitTest As ListViewHitTestInfo = lv.HitTest(e.X, e.Y)
       Me.currentItem = hitTest.SubItem

       With Me.TextBoxLvItem
           .Width = lv.Columns(hitTest.Item.Index).Width
           .Left = (lv.Left + hitTest.SubItem.Bounds.Left + 3)
           .Top = (lv.Top + hitTest.SubItem.Bounds.Top)
           .Text = hitTest.SubItem.Text
           .Show()
           .Focus()
           .SelectAll()
       End With

       lv.SendToBack()

   End Sub

   Private Sub TextBoxLvItem_KeyUp(ByVal sender As Object, ByVal e As KeyEventArgs) _
   Handles TextBoxLvItem.KeyUp

       Select Case e.KeyData

           Case Keys.Return ' Guardar el texto.
               currentItem.Text = DirectCast(sender, TextBox).Text
               DirectCast(sender, TextBox).Hide()

           Case Keys.Escape ' No guardar el texto.
               DirectCast(sender, TextBox).Hide()

           Case Else
               '...

       End Select

   End Sub


PD: No actives el LabelEdit, no es necesario con el código que mostré.

Saludos

Eleкtro

Tienes razón, un fallo tonto. La manera correcta de obtener el índice de la columna sería la siguiente:

Código (vbnet) [Seleccionar]
Dim columnindex As Integer = hitTest.Item.SubItems.IndexOf(hitTest.SubItem)

Con eso ya puedes solucionar el problema.

Por cierto, de nada.

Saludos!








bybaal

Ahora si quedo perfecto   ;-)

Cita de: Eleкtro en  8 Enero 2016, 20:37 PM
Tienes razón, un fallo tonto. La manera correcta de obtener el índice de la columna sería la siguiente:

Código (vbnet) [Seleccionar]
Dim columnindex As Integer = hitTest.Item.SubItems.IndexOf(hitTest.SubItem)

Con eso ya puedes solucionar el problema.

Por cierto, de nada.

Saludos!