Evitar datos duplicados en listview

Iniciado por nolasco281, 10 Mayo 2015, 00:11 AM

0 Miembros y 2 Visitantes están viendo este tema.

nolasco281

Hola como estan.

Mi consulta es la siquiente tengo un listview y no puedo lograr que no me ingrese datos repetidos



Este es mi codigo. de como ingreso los datos. He probado muchas cosas solo pongo el codigo limpio de como ingreso datos para que me den una idea de como hacer para que no me repita datos.

Código (vbnet) [Seleccionar]
Private Sub RadButton4_Click(sender As System.Object, e As System.EventArgs) Handles RadButton4.Click
       If txtArticulosPedidos.Text = "" Or rseCantidadPedido.Text = "0" Then
           RadMessageBox.Show(Me, "No ha seleccionado datos", "Información", MessageBoxButtons.OK, RadMessageIcon.Info)

       Else
           Dim lvItem1 As New ListViewDataItem() 'Variable para los items
           'Agrega a cada columna valores
           Me.lvListaPedidos.Items.Add(lvItem1)
           lvItem1.Item(0) = txtArticulosPedidos.Text
           lvItem1.Item(1) = rseCantidadPedido.Text
       End If

   End Sub


Saludos.
Lo que se puede imaginar... se puede programar.

DarK_FirefoX

#1
Código (vbnet) [Seleccionar]
Dim lvItem1 As New ListViewDataItem()

'Estas dos lineas las subi de lugar pues creo que es más entendible así
lvItem1.Item(0) = RadTextBox21.Text
lvItem1.Item(1) = RadSpinEditor1.Text

'Aquí iría la condición

Me.RadListView1.Items.Add(lvItem1)


Entonces lo que deberías prácticamente es recorrer la colección Items del ListView y ver si existe un ListViewDataItem con esos valores. También puedes hacer uso del método Contains(). Que sería algo como nombreDeTuListView.Items.Contains(listViewItemAComprobar) en un If antes de añadirlo al ListView.

Modifico: Ahh, y lo que tienes que verificar es que el Contains() no se cumpla (devuelva false) antes de añadirlo.

Espero haberte ayudado. Disculpa si no soy más específico en cuanto a sintaxis, pero no estoy tan familiarizado con la sintaxis de VB.NET

PD: Quizás Eleкtro te hecha una mano!

PD: Una sugerencia, deberías usar nombres descriptivos para tus controles y/o variables, de esta manera es más entendible el código

nolasco281

#2
Hola gracias por responder ya lo logre si hay otra forma mas eficiente se los agradeceria

Código (vbnet) [Seleccionar]
Private Sub RadButton4_Click(sender As System.Object, e As System.EventArgs) Handles btnAgregarBoton.Click
        'Verifica que el dato ingresado no exista
        Dim existe As Boolean = False

        For Each lvItem1 In lvListaPedidos.Items 'Recorre el listview
            If lvItem1.Item(0) = txtArticulosPedidos.Text Then 'Compara la columna (subitem de la columna)
                existe = True 'Si lo que hay en listview es igual a lo que hay en el artículo ya existe
                Exit For
            End If
        Next

        'Si es verdadero se muestra este mensaje
        If existe Then
            MessageBox.Show("el item ya existe")
            Return
        End If

        'Si los campos están vacíos no ingresa datos
        If txtArticulosPedidos.Text = "" Or rseCantidadPedido.Text = "0" Then
            RadMessageBox.Show(Me, "No ha seleccionado datos", "Información", MessageBoxButtons.OK, RadMessageIcon.Info)

        Else
            Dim lvItem1 As New ListViewDataItem() 'Variable para los items
            'Agrega a cada columna valores
            Me.lvListaPedidos.Items.Add(lvItem1)
            lvItem1.Item(0) = txtArticulosPedidos.Text
            lvItem1.Item(1) = rseCantidadPedido.Text
        End If

    End Sub


Saludos!
Lo que se puede imaginar... se puede programar.

Eleкtro

#3
Antes de nada, cuando formules una pregunta de este tipo asegúrate de aclarar que estás utilizando los componentes de Telerik, que no todo el mundo los conoce y eso puede confundir a los demás.




Cita de: nolasco281 en 10 Mayo 2015, 05:20 AMsi hay otra forma mas eficiente se los agradeceria

Lo que estás haciendo con el For Each es una solución efectiva, pero en este caso específico donde solo tienes 2 columnas y quieres que no se repita la columna de artículos, deberías asignarle una llave a cada item con el nombre del artículo, eso lo puedes hacer estableciendo un valor a la propiedad ListViewItem.Name, y luego utilizar la función ListView.Items.ContainsKey para determinar si la llave existe.

VB.Net:
Código (vbnet) [Seleccionar]
   Private Sub Test() Handles MyBase.Shown

       Dim articulo As String = "Clavos"
       Dim cantidad As Integer = 40

       Dim lvItem As New ListViewItem({articulo, cantidad.ToString("00")}) With
       {
           .Name = articulo
       }

       Me.ListView1.Items.Add(lvItem)

   End Sub

   Private Sub Button1_Click() Handles Button1.Click

       Dim articulo As String = "Clavos"
       Dim cantidad As Integer = 5

       If Me.ListView1.Items.ContainsKey(articulo) Then
           MessageBox.Show("El articulo ya existe en la lista.", "", MessageBoxButtons.OK, MessageBoxIcon.Error)
       Else
           ' ...
       End If

   End Sub


C-Sharp:
Código (csharp) [Seleccionar]
private void Test()
{
string articulo = "Clavos";
int cantidad = 40;

ListViewItem lvItem = new ListViewItem({articulo, cantidad.ToString("00")}) { Name = articulo };
this.ListView1.Items.Add(lvItem);
}

private void Button1_Click()
{
string articulo = "Clavos";
int cantidad = 5;

if (this.ListView1.Items.ContainsKey(articulo)) {
MessageBox.Show("El articulo ya existe en la lista.", "", MessageBoxButtons.OK, MessageBoxIcon.Error);
} else {
// ...
}
}

//=======================================================
//Service provided by Telerik (www.telerik.com)
//======================================================


Nota: La función ListView.Items.ContainsKey es case-insensitive, es decir, no distingue entre minúsculas y mayúsculas.




Para un RadListView puedes utilizar la función RadListView.FindItemByKey, para asignar la llave a un item lo puedes hacer estableciendo un valor a la propiedad ListViewDataItem.Key

VB.Net:
Código (vbnet) [Seleccionar]
   Private Sub Test() Handles MyBase.Shown

       Dim articulo As String = "Clavos"
       Dim cantidad As Integer = 40

       Dim lvItem As New ListViewDataItem(text:="", values:={articulo, cantidad.ToString("00")}) With
       {
           .Key = articulo
       }

       Me.RadListView1.Items.Add(lvItem)

   End Sub

   Private Sub Button1_Click() Handles Button1.Click

       Dim articulo As String = "Clavos"
       Dim cantidad As Integer = 5

       If Me.RadListView1.FindItemByKey(key:=articulo, searchVisibleItems:=True) IsNot Nothing Then
           RadMessageBox.Show("El articulo ya existe en la lista.", "", MessageBoxButtons.OK, RadMessageIcon.Error)
       Else
           ' ...
       End If

   End Sub


C-Sharp:
Código (csharp) [Seleccionar]
private void Test()
{
string articulo = "Clavos";
int cantidad = 40;

ListViewDataItem lvItem = new ListViewDataItem(text: "", values: {articulo, cantidad.ToString("00")}) { Key = articulo };
this.RadListView1.Items.Add(lvItem);
}

private void Button1_Click()
{
string articulo = "Clavos";
int cantidad = 5;

if (this.RadListView1.FindItemByKey(key: articulo, searchVisibleItems: true) != null) {
RadMessageBox.Show("El articulo ya existe en la lista.", "", MessageBoxButtons.OK, RadMessageIcon.Error);
} else {
// ...
}
}

//=======================================================
//Service provided by Telerik (www.telerik.com)
//=======================================================


Nota: La función RadListView.FindItemByKey es case-sensitive, es decir, distingue entre minúsculas y mayúsculas.

Saludos








Eleкtro

#4
Cita de: DarK_FirefoX en 10 Mayo 2015, 03:47 AMTambién puedes hacer uso del método Contains(). Que sería algo como nombreDeTuListView.Items.Contains(listViewItemAComprobar) en un If antes de añadirlo al ListView.

Cabe mencionar que la función ListView.Items.Contains realiza una comparación de referencias (tanto para un ListView cómo un RadListView, y otros muchos controles de .Net Framework).

¿Que quiere decir esto?, pues que que crear dos instancias del mismo tipo de objeto, en este caso dos ListViewItem distintos que tengan los mismos datos, no los convierte en el mismo objeto, por que tienen referencias distintas.

Ejemplo demostrativo:
Código (vbnet) [Seleccionar]
Dim articulo As String = "Clavos"
Dim cantidad As Integer = 1

Dim lvItem1 As New ListViewItem({articulo, cantidad.ToString("00")})
Dim lvItem2 As New ListViewItem({articulo, cantidad.ToString("00")})

Dim areEqual As Boolean = lvItem1.Equals(lvItem2)

Debug.WriteLine(String.Format("Son Iguales?: {0}", areEqual))


C#:
Código (csharp) [Seleccionar]
string articulo = "Clavos";
int cantidad = 1;

ListViewItem lvItem1 = new ListViewItem({articulo, cantidad.ToString("00")});
ListViewItem lvItem2 = new ListViewItem({articulo, cantidad.ToString("00")});

bool areEqual = lvItem1.Equals(lvItem2);

Debug.WriteLine(string.Format("Son Iguales?: {0}", areEqual));


Saludos!








nolasco281

#5
CitarAntes de nada, cuando formules una pregunta de este tipo asegúrate de aclarar que estás utilizando los componentes de Telerik, que no todo el mundo los conoce y eso puede confundir a los demás.

Lo tendre muy en cuenta.
==============================

Hola estaba probando lo de case sensitive pero todavía no me detecta si la palabra esta en mayus o no.

que estoy haciendo mal.

Código (vbnet) [Seleccionar]
Dim lvItem1 As New ListViewDataItem()
       lvItem1.Key = txtArticulosPedidos.Text

       If Me.lvListaPedidos.FindItemByKey(key:=txtArticulosPedidos.Text, searchVisibleItems:=True) IsNot Nothing Then
           RadMessageBox.Show("El articulo ya existe en la lista.", "", MessageBoxButtons.OK, RadMessageIcon.Error)
       Else

           Me.lvListaPedidos.Items.Add(lvItem1)
           lvItem1.Item(0) = txtArticulosPedidos.Text
           lvItem1.Item(1) = rseCantidadPedido.Text
       End If


Saludos Gracias.


Lo que se puede imaginar... se puede programar.

Eleкtro

#6
No estás haciendo nada mal, simplemente la llave no se encuentra por que las minúsculas/mayúsculas no coinciden, o el texto que estás buscando no existe cómo llave.

Para condicionar el resultado, asigna la llave de los items en minúscula:
Código (vbnet,5) [Seleccionar]
Dim articulo As String = "Clavos"
Dim cantidad As Integer = 40

Dim lvItem As New ListViewDataItem(text:="", values:={articulo, cantidad.ToString("00")}) With
   { .Key = articulo.Trim.ToLower }

Me.RadListView1.Items.Add(lvItem)


Y entonces busca en minúscula:
Código (vbnet,4,8) [Seleccionar]
Dim articulo As String = txtArticulosPedidos.Text.Trim
Dim cantidad As String = Convert.ToInt32(rseCantidadPedido.Text).ToString("00")

If Me.lvListaPedidos.FindItemByKey(key:=articulo.ToLower, searchVisibleItems:=True) IsNot Nothing Then
   RadMessageBox.Show("El articulo ya existe en la lista.", "", MessageBoxButtons.OK, RadMessageIcon.Error)
Else
   Dim lvItem As New ListViewDataItem(text:="", values:={articulo, cantidad} with
       { .Key = articulo.ToLower }
   Me.lvListaPedidos.Items.Add(lvItem)
End If


Saludos








nolasco281

#7
Muchas gracias Eleкtro

Lo probé de las dos formas y funciona perfecto. Lo entendí todo lo único que investigare es el .trim

Gracias por lo de las llaves, y agregar condiciones a ellas como llaves. (Valga la redundancia)

Saludos  ;-) ;-)

Código (vbnet) [Seleccionar]
Dim lvItem1 As New ListViewDataItem()
       lvItem1.Key = txtArticulosPedidos.Text.ToLower


       If Me.lvListaPedidos.FindItemByKey(key:=txtArticulosPedidos.Text.ToLower, searchVisibleItems:=False) IsNot Nothing Then
           RadMessageBox.Show("El articulo ya existe en la lista.", "", MessageBoxButtons.OK, RadMessageIcon.Error)
       Else
           Me.lvListaPedidos.Items.Add(lvItem1)
           lvItem1.Item(0) = txtArticulosPedidos.Text
           lvItem1.Item(1) = rseCantidadPedido.Text
       End If


Veo que quito este, lo dejo por si a alquien le sirve de esta forma lo entendi. : ). ahora vere el que modifico

Código (vbnet) [Seleccionar]
Dim key As String = txtArticulosPedidos.Text.Trim

       If Me.lvListaPedidos.FindItemByKey(key:=key.ToLower, searchVisibleItems:=True) IsNot Nothing Then
           RadMessageBox.Show("El articulo ya existe en la lista.", "", MessageBoxButtons.OK, RadMessageIcon.Error)
       Else
           Dim lvItem1 As New ListViewDataItem
           lvItem1.Key = key.ToLower
           Me.lvListaPedidos.Items.Add(lvItem1)
           lvItem1.Item(0) = key
           lvItem1.Item(1) = rseCantidadPedido.Text
       End If


Falto ) despues de }
Código (vbnet) [Seleccionar]
Dim lvItem As New ListViewDataItem(text:="", values:={articulo, cantidad} with

Código (vbnet) [Seleccionar]
'Dim cantidad As String = Convert.ToInt32(rseCantidadPedido.Text).ToString("00")

Gracias le da un mejor formato a la cantidad vere si no me causa problema en la BD ya que si no me equivoco lo manda como string.




Muchas gracias de nuevo Eleкtro
Lo que se puede imaginar... se puede programar.

Eleкtro

#8
Parezco retrasado, estoy viendo todo el rato que publicas código en VB.Net pero yo tenía metido en la cabeza que solo manejabas C# por que te confundí con otro usuario y por eso te puse el código en C# aunque solo veia Vb.Net, no era por "presumir" ni nada parecido jaja, el código en C# la verdad es que quedó de más.




Cita de: nolasco281 en 10 Mayo 2015, 11:06 AMinvestigare es el .trim

La función Trim, TrimStart y TrimEnd lo que hacen es eliminar los espacios del principio o del final de un String, pero puedes utilizar sus overloads para especificar otros (uno, o varios) caracteres a eliminar.

En el ejemplo de arriba yo solo utilizo Trim cómo modo preventivo por si a lo mejor en tu aplicación te estaba fallando por que escribias algún espacio al principio o al final.




Cita de: nolasco281 en 10 Mayo 2015, 11:06 AM
Código (vbnet) [Seleccionar]
'Dim cantidad As String = Convert.ToInt32(rseCantidadPedido.Text).ToString("00")

Gracias le da un mejor formato a la cantidad vere si no me causa problema en la BD ya que si no me equivoco lo manda como string.

Si quieres enviarlo a la DataBase como valor de tipo Integer entonces solo tienes que convertir el string formateado:
Código (vbnet) [Seleccionar]
Dim value as Integer = CInt("05")
o también:
Código (vbnet) [Seleccionar]
Dim value as Integer = Convert.ToInt32("05")

Saludos








DarK_FirefoX

Cita de: Eleкtro en 10 Mayo 2015, 09:52 AM
Cabe mencionar que la función ListView.Items.Contains realiza una comparación de referencias (tanto para un ListView cómo un RadListView, y otros muchos controles de .Net Framework).

¿Que quiere decir esto?, pues que que crear dos instancias del mismo tipo de objeto, en este caso dos ListViewItem distintos que tengan los mismos datos, no los convierte en el mismo objeto, por que tienen referencias distintas.

Ejemplo demostrativo:
Código (vbnet) [Seleccionar]
Dim articulo As String = "Clavos"
Dim cantidad As Integer = 1

Dim lvItem1 As New ListViewItem({articulo, cantidad.ToString("00")})
Dim lvItem2 As New ListViewItem({articulo, cantidad.ToString("00")})

Dim areEqual As Boolean = lvItem1.Equals(lvItem2)

Debug.WriteLine(String.Format("Son Iguales?: {0}", areEqual))


C#:
Código (csharp) [Seleccionar]
string articulo = "Clavos";
int cantidad = 1;

ListViewItem lvItem1 = new ListViewItem({articulo, cantidad.ToString("00")});
ListViewItem lvItem2 = new ListViewItem({articulo, cantidad.ToString("00")});

bool areEqual = lvItem1.Equals(lvItem2);

Debug.WriteLine(string.Format("Son Iguales?: {0}", areEqual));


Saludos!

Tienes toda la razón. Entendido, la verdad no se porque cometí ese error! xD

Por otro lado:

Cita de: EleкtroParezco retrasado, estoy viendo todo el rato que publicas código en VB.Net pero yo tenía metido en la cabeza que solo manejabas C# por que te confundí con otro usuario y por eso te puse el código en C# aunque solo veia Vb.Net, no era por "presumir" ni nada parecido jaja, el código en C# la verdad es que quedó de más.

Agradezco que hayas publicado también el código en C#, yo soy el que maneja C# y no VB.NET, quizás por eso lo hiciste. Gracias