¿Me pueden decir alguna manera sencilla para ordenar alfabéticamente la columna de "problem" al pulsar click sobre el nombre de la columna?
O al menos, ¿Como se llama el evento que debo manejar? :S
Gracias.
(http://img802.imageshack.us/img802/7933/prtscrcapturecd.jpg)
hay varias maneras pero una de las mejores es usar la interface llamada IComparer. aca te paso la clase que usaba:
Public Class COrdenarListview
Implements IComparer
Private vIndiceColumna As Integer
Private vTipoOrden As SortOrder
Public Sub New(ByVal pIndiceColumna As Integer, ByVal pTipoOrden As SortOrder)
vIndiceColumna = pIndiceColumna
vTipoOrden = pTipoOrden
End Sub
Public Function Ordenar(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
Dim item_x As ListViewItem = DirectCast(x, ListViewItem)
Dim item_y As ListViewItem = DirectCast(y, ListViewItem)
Dim string_x As String
If item_x.SubItems.Count <= vIndiceColumna Then
string_x = ""
Else
string_x = item_x.SubItems(vIndiceColumna).Text
End If
Dim string_y As String
If item_y.SubItems.Count <= vIndiceColumna Then
string_y = ""
Else
string_y = item_y.SubItems(vIndiceColumna).Text
End If
If vTipoOrden = SortOrder.Ascending Then
If IsNumeric(string_x) And IsNumeric(string_y) Then
Return Val(string_x).CompareTo(Val(string_y))
ElseIf IsDate(string_x) And IsDate(string_y) Then
Return DateTime.Parse(string_x).CompareTo(DateTime.Parse(string_y))
Else
Return String.Compare(string_x, string_y)
End If
Else
If IsNumeric(string_x) And IsNumeric(string_y) Then
Return Val(string_y).CompareTo(Val(string_x))
ElseIf IsDate(string_x) And IsDate(string_y) Then
Return DateTime.Parse(string_y).CompareTo(DateTime.Parse(string_x))
Else
Return String.Compare(string_y, string_x)
End If
End If
End Function
End Class
luego para usarla tenes que usar el evento ColumnClick de esta forma:
Private Sub lv_ColumnClick(ByVal sender As Object, ByVal e As System.Windows.Forms.ColumnClickEventArgs) Handles lv.ColumnClick
Dim vIndiceColumna As ColumnHeader = lv.Columns(e.Column)
Dim vTipoOrden As System.Windows.Forms.SortOrder
If vColumnaOrden Is Nothing Then
vTipoOrden = SortOrder.Ascending
vOrden = SortOrder.Ascending
Else
If vIndiceColumna.Equals(vColumnaOrden) Then
If vOrden = SortOrder.Ascending Then
vTipoOrden = SortOrder.Descending
vOrden = SortOrder.Descending
Else
vTipoOrden = SortOrder.Ascending
vOrden = SortOrder.Ascending
End If
Else
vTipoOrden = SortOrder.Ascending
vOrden = SortOrder.Ascending
End If
End If
vColumnaOrden = vIndiceColumna
lv.ListViewItemSorter = New COrdenarListview(e.Column, vTipoOrden)
lv.Sort()
End Sub
esta lo que hace es que te "detecta" por asi decirlo, el tipo de datos de la columna y te lo ordena dependiendo ese tipo de dato, por ejemplo si tenes numeros te lo ordena como numero y no como string, te detecta las fechas y los strings comunes, y tiene los 2 metodos ascendente y descendente.
digo "usaba", porque desde hace rato ya en .NET uso el ObjectListview, es lejos el mejor control creado para .NET, el cual te facilita todo, es mil veces mejor que el Listview de .NET, y tambien te hace todo automatico el tema del ordenamiento. te ahorras todo estos temas de ensuciar el codigo con cada cosita extra que uno necesita hacer.
saludos.
A mi me gustaría usar el objectlistview pero no tengo ni idea de como añadir un item,
Seba123Neo, ¿Serías tán amable de enseñarme como crear/agregar un objeto para añadirlo al ObjectListView?, es decir, un item. ¿?
Lo intenté hacer pero es distinto de hacer como se haría con el ListView normal.
PD: Gracias por la class.
en el objectlistview los items no se agregan como en el comun, justamente se llama "object" porque se maneja todo con objetos, o sea tenes que crear una clase con las propiedades (que serian las columnas) que va a tener el listview y entonces despues asignas esa clase al listview y automaticamente te lo detecta y se arma solo. para llenar items simplemente creas una lista de las clase es que creas y las vas llenado con datos, cada clase despues seria un registro. si te bajas este control ya viene con un proyecto de como se usa, esta en C# pero se entiende bien la logica.
despues creo un post mostrando como se usa.
Cita de: seba123neo en 31 Diciembre 2012, 16:53 PMdespues creo un post mostrando como se usa.
Deseando ver el mini-tutorial ;D, nos servirá a todos, además es un magnifico control.
PD: La explicación se me ha quedado corta XD, de todas formas lo intentaré a ver...
Saludos
Cita de: EleKtro H@cker en 31 Diciembre 2012, 17:28 PM
Deseando ver el mini-tutorial ;D, nos servirá a todos, además es un magnifico control.
PD: La explicación se me ha quedado corta XD, de todas formas lo intentaré a ver...
Saludos
si lo necesitas urgente, avisame y por teamviewver se te enseña rapido, dificil no es XD
Cita de: spiritdead en 1 Enero 2013, 00:24 AM
si lo necesitas urgente, avisame y por teamviewver se te enseña rapido, dificil no es XD
Gracias spiritdead pero no me urge, aún estoy aprendiendo a usar el listview convencional.
@seba123Neo
¿Como lo hago funcionar?
Me da error en las variables:
vColumnaOrden
vOrden
Dicen que no están declaradas, y no se con que tipo de valor debo setearlas ni nada xD
Private Sub GListView_ColumnClick(ByVal sender As Object, ByVal e As System.Windows.Forms.ColumnClickEventArgs) Handles GListView.ColumnClick
Dim vIndiceColumna As ColumnHeader = GListView.Columns(e.Column)
Dim vTipoOrden As System.Windows.Forms.SortOrder
If vColumnaOrden Is Nothing Then
vTipoOrden = SortOrder.Ascending
vOrden = SortOrder.Ascending
Else
If vIndiceColumna.Equals(vColumnaOrden) Then
If vOrden = SortOrder.Ascending Then
vTipoOrden = SortOrder.Descending
vOrden = SortOrder.Descending
Else
vTipoOrden = SortOrder.Ascending
vOrden = SortOrder.Ascending
End If
Else
vTipoOrden = SortOrder.Ascending
vOrden = SortOrder.Ascending
End If
End If
vColumnaOrden = vIndiceColumna
GListView.ListViewItemSorter = New COrdenarListview(e.Column, vTipoOrden)
GListView.Sort()
End Sub
EDITO:Seba123Neo, si no he captado mal la idea, al final lo he hecho así, y funciona bien, pero no sé si es peor que tu snippet:
' En las declaraciones...
Dim ColumnOrder As String = "Down"
Private Sub GListView_ColumnClick(ByVal sender As Object, ByVal e As System.Windows.Forms.ColumnClickEventArgs) Handles GListView.ColumnClick
If ColumnOrder = "Down" Then
Me.GListView.ListViewItemSorter = New COrdenarListview(e.Column, SortOrder.Ascending)
GListView.Sort()
ColumnOrder = "Up"
ElseIf ColumnOrder = "Up" Then
Me.GListView.ListViewItemSorter = New COrdenarListview(e.Column, SortOrder.Descending)
GListView.Sort()
ColumnOrder = "Down"
End If
End Sub
estimados:
he probado el codigo fuente y tambien otro muy similar de el guille, y ambos me resultan muy lentos. aproximadamente 30 segundos para una tabla 30 filas y 2 columnas...!!!
al hacer clic en la primera columna que solo tiene numeros no hay problema, pero al ordenar por la segunda columna, que es texto, se demora demasiado.
alguna sugerencia... pese a que han pasado pvarios años desde el ultimo post.
pd: estoy trabajando en vb.net 2010.
saludos.
Cita de: phetete en 12 Enero 2016, 21:00 PMalguna sugerencia...
El código del compañero @
seba123Neo y cualquier comparer en general no tiene misterio, se implementa la interfáz
IComparer o un type que la implemente (ej. para texto:
CaseInsensitiveComparer) y se implementan los métodos base, es el modelo standard a seguir para implementar dicha funcionalidad de manera correcta, así que si te tarda digamos más de 2 segundos en ordenar entonces seguramente el problema es ajeno al comparer.
· ¿Tal vez estés utilizando un listview de terceros que sea muy "
pesado", o una cantidad de datos muy "
pesada"?.
· Si las circunstancias lo permiten siempre puedes probar a utilizar el modo virtual para aumentar en gran medida el rendimiento del listview:
- ListView.VirtualMode Property - MSDN (https://msdn.microsoft.com/es-es/library/system.windows.forms.listview.virtualmode%28v=vs.110%29.aspx)
De todas formas, eso es solo una sugerencia adicional y ajena al problema real de los 30 segundos de ordenamiento.
· Revisa los controladores de eventos de tu listview para verificar si estás haciendo algo incorrecto con los items que provoque ese exceso de tiempo en el ordenamiento... y publica el código relevante, de lo contrario dudo mucho que alguien te pueda ayudar, ya que como digo el problema seguramente no sea del comparer (a menos que la lógica del comparer que estés usando sea tan incorrecta como para provocar ese tipo de problema).
Te sugiero reemplazar la lógica de ordenamiento que estés utilizando y probar con el siguiente código fuente extraido de la próxima versión (sin publicar todavía) de mi API ElektroKit:
(http://i.imgur.com/er0AiUl.png) (https://github.com/ElektroStudios/ElektroKit/)
- ListViewColumnSorter.vb (http://pastebin.com/5dMrv1n7)
- TextComparer.vb (http://pastebin.com/igUSGRr6)
- NumericComparer.vb (http://pastebin.com/bYFQauGJ)
- DateComparer.vb (http://pastebin.com/Wp8Wgtyb)
- ComparerResult Enum (http://pastebin.com/QcTza700)
Ejemplo de uso:
Public Class Form1 : Inherits Form
Friend WithEvents MyListView As New ListView
Private sorter As New ListViewColumnSorter
Public Sub New()
MyClass.InitializeComponent()
With Me.MyListView
' Set the sorter, our ListViewColumnSorter.
.ListViewItemSorter = sorter
' The initial direction for the sorting.
.Sorting = SortOrder.Ascending
' Set the initial sort-modifier.
sorter.SortModifier = SortModifiers.SortByText
' Add some columns.
.Columns.Add("Text").Tag = SortModifiers.SortByText
.Columns.Add("Numbers").Tag = SortModifiers.SortByNumber
.Columns.Add("Dates").Tag = SortModifiers.SortByDate
' Adjust the column sizes.
For Each col As ColumnHeader In Me.MyListView.Columns
col.Width = 100
Next
' Add some items.
.Items.Add("hello").SubItems.AddRange({"2", "11/11/2000"})
.Items.Add("yeehaa!").SubItems.AddRange({"1", "9/9/1999"})
.Items.Add("El3ktr0").SubItems.AddRange({"100", "21/08/2014"})
.Items.Add("wow").SubItems.AddRange({"10", "11-11-2000"})
' Styling things.
.Dock = DockStyle.Fill
.View = View.Details
.FullRowSelect = True
End With
With Me ' Styling things.
.Size = New Size(400, 200)
.FormBorderStyle = Global.System.Windows.Forms.FormBorderStyle.FixedSingle
.MaximizeBox = False
.StartPosition = FormStartPosition.CenterScreen
.Text = "ListViewColumnSorter TestForm"
End With
Me.Controls.Add(Me.MyListView)
End Sub
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Handles the <see cref="ListView.ColumnClick"/> event of the <see cref="MyListView"/> control.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
Private Sub MyListView_ColumnClick(ByVal sender As Object, ByVal e As ColumnClickEventArgs) _
Handles MyListView.ColumnClick
Dim lv As ListView = DirectCast(sender, ListView)
' Dinamycaly sets the sort-modifier to sort the column by text, number, or date.
sorter.SortModifier = DirectCast(lv.Columns(e.Column).Tag, SortModifiers)
' Determine whether clicked column is already the column that is being sorted.
If (e.Column = sorter.ColumnIndex) Then
' Reverse the current sort direction for this column.
If (sorter.Order = SortOrder.Ascending) Then
sorter.Order = SortOrder.Descending
Else
sorter.Order = SortOrder.Ascending
End If
Else
' Set the column number that is to be sorted, default to ascending.
sorter.ColumnIndex = e.Column
sorter.Order = SortOrder.Ascending
End If ' e.Column
' Perform the sort.
lv.Sort()
End Sub
End Class
Cita de: phetete en 12 Enero 2016, 21:00 PMhan pasado pvarios años desde el ultimo post.
Está prohibido revivir temas antiguos, si sigues teniendo ese problema con el listview entonces debes formular tus dudas en un nuevo hilo y si quieres puedes hacer referencia a este u otro hilo poniendo la url para mencionar el contenido/cçodigo del post o contestar a cualquiera de las preguntas que te hice...
Tema cerrado.Saludos!