Saludos amigos, soy yo nuevamente molestando, tengo un problema con un listbox.
Verán, estoy haciendo una aplicación dónde esta cargue 3 rutas de un archivo sobre un objeto, posteriormente cuando ese objeto esté "relleno" lo inserto en un listbox, el problema se inicia cuando quiero obtener el valor de ese listbox el cuál según el vs el valor es nothing pero curiosamente a la hora de depurarlo los valores me dice que se ha rellenado correctamente.
Este es el código del objeto
Public Class Archivos
'Atributos de la clase
Private str_ruta_archivo_entradas As String = String.Empty
Private str_ruta_archivo_valorizado As String = String.Empty
Private str_ruta_archivo_salidas As String = String.Empty
Private str_entradas_salidas_excluir As ArrayList
'Métodos de acceso
Public Property Str_Ruta_Archivo_E() As String
Get
Return Me.str_ruta_archivo_entradas
End Get
Set(ByVal Value As String)
Me.str_ruta_archivo_entradas = Value
End Set
End Property
Public Property Str_Ruta_Archivo_Val As String
Get
Return Me.str_ruta_archivo_valorizado
End Get
Set(ByVal Value As String)
Me.str_ruta_archivo_valorizado = Value
End Set
End Property
Public Property Str_Salidas As String
Get
Return Me.str_ruta_archivo_salidas
End Get
Set(ByVal Value As String)
Me.str_ruta_archivo_salidas = Value
End Set
End Property
Public Property Str_ES_Excluir As ArrayList
Get
Return Me.str_entradas_salidas_excluir
End Get
Set(ByVal Value As ArrayList)
Me.str_entradas_salidas_excluir = Value
End Set
End Property
'Constructor
Public Sub New(ByVal str_ruta_e As String, ByVal str_ruta_archivo_val As String, ByVal str_rutas_array As ArrayList, ByVal str_archivo_salidas As String)
str_ruta_archivo_entradas = str_ruta_e
str_ruta_archivo_salidas = str_archivo_salidas
str_ruta_archivo_valorizado = str_ruta_archivo_val
str_entradas_salidas_excluir = str_rutas_array
End Sub
Public Sub New()
str_ruta_archivo_entradas = String.Empty
str_ruta_archivo_valorizado = String.Empty
str_ruta_archivo_salidas = String.Empty
str_entradas_salidas_excluir = Nothing
End Sub
End Class
Aquí es dónde lo inserto mediante unos diálogos y un botón.
Try
Dim operaciones As Archivos
Dim str_ruta_archivo_E As String = String.Empty
Dim str_ruta_archivo_S As String = String.Empty
Dim str_ruta_archivo_Inv As String = String.Empty
Dim obj_array As New ArrayList
Dim int_cont As Integer = 0
'Cargando archivo de entradas/salidas
dlg_Abrir.Title = "Seleccione el archivo de excel (archivo de entradas) a procesar"
dlg_Abrir.DefaultExt = ".xlsx"
lbl_estado.Text = "Cargando datos del archivo de entradas..."
If dlg_Abrir.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
str_ruta_archivo_E = dlg_Abrir.FileName()
End If
'Cargando archivo de salidas
dlg_Abrir.Title = "Seleccione el archivo de excel (archivo de salidas) a procesar"
dlg_Abrir.DefaultExt = ".xlsx"
lbl_estado.Text = "Cargando datos del archivo de salidas..."
If dlg_Abrir.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
str_ruta_archivo_S = dlg_Abrir.FileName()
End If
'Cargando archivo valorizado
dlg_Abrir.Title = "Seleccione el archivo de excel (archivo valorizado correspondiente a esas entradas/salidas) a procesar"
dlg_Abrir.DefaultExt = ".xlsx"
lbl_estado.Text = "Cargando datos del archivo valorizado correspondiente a esas entradas/salidas..."
If dlg_Abrir.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
str_ruta_archivo_Inv = dlg_Abrir.FileName()
End If
For Each valor In lt_salidas_entradas_excluir.Items
obj_array.Add(valor)
Next
operaciones = New Archivos(str_ruta_archivo_E, str_ruta_archivo_Inv, obj_array, str_ruta_archivo_S)
lt_Archivos.Items.Add(operaciones)
Catch ex As Exception
MsgBox("Hubo un error cargando el archivo del contenedor.")
End Try
Mediante un menústrip de un contextmenú o menú contextual genero un pequeño dialogo y lo que hago es que quiero mostrar la información de ese objeto (que por cierto sería genial si alguno de uds sabe como ponerle texto más "bonito" a ese objeto en ese listbox sin alterar su valor como un combobox con sus propiedades de display member).
Private Sub MostrarInformaciónToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles MostrarInformaciónToolStripMenuItem.Click
Dim obj As Archivos
obj = lt_Archivos.SelectedValue
MsgBox(obj.Str_Ruta_Archivo_E)
End Sub
Curiosamente cuando lo depuro cómo les menciono arriba me dice que el objeto está correctamente insertado y tiene un valor pero a la hora de "jalarlo" no me sale nada, me preocupa porque necesito manipular ese objeto para el resto del proyecto, si uds saben algo se los agradecería demasiado.
Ya pude, lo dejo para que otros si tienen la duda puedan resolverlo...
Dim obj As Archivos
obj = CType(lt_Archivos.SelectedItem, Archivos)
Y ya con la variable "obj" pueden jugar.
Ahora bien, lo que no he podido hacer aún es lo siguiente:
Quiero que cuando se inserte ese objeto en lugar de decir el nombre del objeto diga "Archivo1,Archivo2", lo que hice fue cambiar el método toString para que diga archivo pero quiero tener un contador para así el usuario pueda diferenciar entre los objetos del listbox.
Lo que hice fue esto:
Public Overrides Function ToString() As String
Return str_mostrar_texto & int_cont
End Function
End Class
Lógicamente agregué el atributo "str_mostrar_texto" en la clase así como sus gets y sets.
Entonces no se si alguno tendrá alguna sugerencia? ya lo intenté con un integer global pero no suma el contador y en todas da 0.
Muchas gracias desde ya.
Carece de sentido que en el diseño de la clase "Archivos" implementes un contador de ningún tipo, ya que si no te he entendido mal, la clase archivos se supone que sirve para representar una serie de rutas de archivos que están relacionados entre si, pues bien, eso es correcto, pero en ese caso eso sería todo lo que debes hacer con esa clase...
Así que deberías dar el diseño de esa clase por finalizado, y a partir de ahí eres tú el que debe declarar un contador (fuera de la clase "Archivos") y añadir/mostrar ese contador al añadir cada uno de esos items al ListBox, no al revés, es decir, no debe ser la clase "Archivos" la que deba representar por si misma y mostrar un índice al ser representado como texto ( Archivos.ToString() ) en un control, eso es mezclar cosas que no tienen nada que ver, y por ende no tiene sentido productivo. No se si me he explicado suficientemente bien.
De todas formas no tengo muy claro por que sientes la necesidad de usar una variable-contador que actue como índice de los items representados en el listbox, es decir, el índice del elemento lo puedes obtener directamente en la lista de elementos de dicho ListBox y mostrarlo si quieres junto al nombre del elemento, algo como por ejemplo:
Me.ListBox1.BeginUpdate()
For i As Integer = 0 To (Me.ListBox1.Items.Count - 1)
Me.ListBox1.Items(i) = String.Format("[{0:00}] {1}", i, Me.ListBox1.Items(i))
Next
Me.ListBox1.EndUpdate()
...o en su defecto siempre puedes añadir las instancias de la clase "Archivos" a un diccionario u otra colección apropiada para tus necesidades, en la que usar la "llave" como índice, y luego mostrarlo al añadir el valor/elemento en el listbox.
Pero en fin. Dices que ya lo intentaste con un "integer global" (imagino que te refieres a que usaste el modificador de visibilidad Public Shared) pero "no suma el contador y en todas da 0". Todo esto no se entiende mucho. Para empezar, no se sabe donde lo declaraste, ni cuando y como incrementas su valor, pero algo parece evidente, y es que si su valor siempre es 0, será que la unidad de código donde incrementas el valor nunca se llega a ejecutar, o si se ejecuta pero en realidad no llegas a incrementar el valor. No se pueden sacar otras conclusiones mientras no aportes más información.
Saludos.
Muchas gracias elektro por responder, siempre con mucho conocimiento por dar y aprendo mucho de tu persona.
Mira, lo único que quiero que cuando agregue ese objeto al listbox no aparezca como texto en cada item el valor del objeto, es decir NO quiero que aparezca como "nombredel proyecto.objeto" sino que en ese texto aparezca como archivo1, archivo2,archivo3 sin alterar lógicamente sus atributos.
La variable local la declaré tanto en la clase del form dónde estaba ese listbox como erroneamente tambien en ese objeto.
Lo intenté con el método toString() para en lugar de "nombredelproyecto.objeto" se mostrara Archivo pero queria concatenarle un contador que se fuera incrementando, pero no lo logré.
Luego de un montón de intentos lo logré!! ;-).
En el método del constructor del objeto archivo lo agregué cómo parámetro:
Public Sub New(ByVal str_ruta_e As String, ByVal str_ruta_archivo_val As String, ByVal str_rutas_array As ArrayList, ByVal str_archivo_salidas As String, ByVal int_cont As Integer)
str_ruta_archivo_entradas = str_ruta_e
str_ruta_archivo_salidas = str_archivo_salidas
str_ruta_archivo_valorizado = str_ruta_archivo_val
str_entradas_salidas_excluir = str_rutas_array
int_contador = int_cont
End Sub
Posteriormente en el form, declaré la variable como pública:
Public int_contador
Modifiqué el método para que tuviera como parámetro la variable:
Private Sub cargar_archivos(ByVal int_cont As Integer)
..
end sub
LLamé al método en el botón:
Private Sub btn_Cargar_Archivos_Click(sender As Object, e As EventArgs) Handles btn_Cargar_Archivos.Click
int_contador = int_contador + 1
cargar_archivos(int_contador)
Agregándolo finalmente así al listbox:
lt_Archivos.Items.Add(New Archivos(str_ruta_archivo_E, str_ruta_archivo_Inv, obj_array, str_ruta_archivo_S, int_cont))
Gracias por leerme.
Primero que nada, y disculpa que te lo diga pero es que realmene se me hace horrible ver tanto guión bajo junto. No se como tú te entiendes con eso, pero a mi se me hace muy dificil/tedioso la lectura de tanto guión bajo.
El caso es que no estás siguiendo las convenciones de nomenclaturas recomendadas para la programación .NET, y sin entrar mucho en detalle te puedo decir que basicamente consiste en usar
Camel case para casi todos los tipos de miembros indiferentemente de su modificador de visibilidad (excepto algunos casos, pero ya dije que sin entrar en muchos detalles).
Aparte de eso, yo en tu lugar sellaría la clase
Archivos, quitaría la asignación de un valor inicial (innecesario) en los campos str_*, y los constructores los dejaría así:
Public NotInheritable Class Archivos
Private str_ruta_archivo_entradas As String
Private str_ruta_archivo_valorizado As String
Private str_ruta_archivo_salidas As String
Private str_entradas_salidas_excluir As ArrayList
'...
Public Sub New()
' Esta llamada es completamente opcional y solo lo muestro para proveer mayor flexibilidad de código (al poder especificar un valor inicial).
' Me.New(String.Empty, String.Empty, Nothing, String.Empty)
End Sub
Public Sub New(ByVal str_ruta_e As String, ByVal str_ruta_archivo_val As String, ByVal str_rutas_array As ArrayList, ByVal str_archivo_salidas As String)
str_ruta_archivo_entradas = str_ruta_e
str_ruta_archivo_valorizado = str_ruta_archivo_val
str_entradas_salidas_excluir = str_rutas_array
str_ruta_archivo_salidas = str_archivo_salidas
End Sub
End Class
...eso suponiendo que realmente quieras declarar un constructor por defecto sin parámetros, de lo contrario:
' ...
Private Sub New()
End Sub
Public Sub New(ByVal str_ruta_e As String, ByVal str_ruta_archivo_val As String, ByVal str_rutas_array As ArrayList, ByVal str_archivo_salidas As String)
str_ruta_archivo_entradas = str_ruta_e
str_ruta_archivo_valorizado = str_ruta_archivo_val
str_entradas_salidas_excluir = str_rutas_array
str_ruta_archivo_salidas = str_archivo_salidas
End Sub
' ...
Es más, esas 70 lineas que ocupa la clase Archivos lo puedes simplificar a 15 o 20 lineas declarando auto-propiedades, en lugar de declarar propiedades con su getter y setter y su campo de apoyo o backing field, resulta innecesario en ese diseño de clase
Archivos, pero bueno, eso no te lo he mostrado por que ahora mismo no recuerdo si fue a partir de Visual Studio 2015 / VB.NET 14.0 o cuando se implementó esta característica, o fue a partir de Visual Studio 2017 / VB.NET 15.
Cita de: Yaldabaot en 22 Marzo 2019, 22:25 PM
Curiosamente cuando lo depuro cómo les menciono arriba me dice que el objeto está correctamente insertado y tiene un valor pero a la hora de "jalarlo" no me sale nada, me preocupa porque necesito manipular ese objeto para el resto del proyecto, si uds saben algo se los agradecería demasiado.
Debes usar la propiedad
ListBox.SelectedItem en vez de
ListBox.SelectedValue, ya que no especificaste ningún miembro para la propiedad
ListBox.ValueMember, normal que te salte una excepción de referencia nula...
Te muestro un ejemplo reducido:
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
Dim test As New Archivos("test", "test", New ArrayList(), "test")
ListBox1.Items.Add(test)
End Sub
Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedIndexChanged
Dim test As Archivos = DirectCast(Me.ListBox1.SelectedItem, Archivos)
MsgBox(test .ToString)
End Sub
Saludos
Gracias elektro, tomaré en cuenta las recomendaciones, y no, no uso 2017, no lo tengo, el que estoy usando es el 2015.