Buenas con todos amigos, les pido una ayuda, quiero usar los checkbox como si fueran un radiobutton dentro de un listview, pues quisiera que solo se pudiera elegir un item de una lista, como veo que no hay "Radiobutton" dentro del listview pienso hacerlo con los checkbox que si los tiene integrados, mi consulta es como lo puedo implementar, Gracias.

Usar Checkbox como Radiobutton en Listview
#1
Posted 18 February 2016 - 09:02 AM
#2
Posted 18 February 2016 - 09:28 AM
Ummm. No lo he probado pero en lo primero que pensaría es capturar el evento OnClic del TListView y en él guardar el índice del elemento "seleccionado". Recorrer la lista, y destildar todos los items distinto al seleccionado.
Ahora no tengo a manos CodeTyphon como para jugar un rato. Pero no creo que sea tan complicado traducir en código mis palabras.
La otra posibilidad es fijarte si no hay algún componente que implemente esta funcionalidad.
Saludos,
#3
Posted 18 February 2016 - 01:29 PM
Yo lo hice alguna vez, solo que hay que tener en cuenta el manejo del onclick, se selecciona el ítem, se coloca el manejo del onclick = Nil, se deseleccionan todos los checkboxes, se selecciona el checkbox requerido y finalmente se asigna nuevamente el evento OnClick = MiEventoOnclick.
Saludos.
#4
Posted 18 February 2016 - 03:36 PM
El control TListView provee el evento OnItemChecked, no hay hay que recurrir a hacks extraños como andar reasignando eventos
Este es un ejemplo trivial
procedure TForm1.ListView1ItemChecked(Sender: TObject; Item: TListItem); begin if Item.Checked then ShowMessageFmt('Item %d %s checked', [Item.Index, Item.Caption]) else ShowMessageFmt('Item %d %s unchecked', [Item.Index, Item.Caption]); end;
Yo derivaria de TListView y agregaria una variable privada donde se mantenga una referencia al objeto con Checked := True
De esta manera el codigo es mas facil ya que si guardas solamente el indice del elemento tildado, cualquier operatoria con los elementos (ordenar, mover, eliminar, agregar) va a requerir actualizar esa variable; lo mas practico es guardar el objeto TListItem que se tildo y listo.
La clase TListItem ya hace lo de "guardar el indice", en su propiedad Index, la cual es actualizada correctamente por la clase TListView.
En la clase derivada, deberias interceptar el mismo evento, desmarcando antes el elemento tildado (si existe) y luego guardando el ultimo
Muy limpio, eficiente y sencillo
#5
Posted 18 February 2016 - 04:31 PM
Es que para que funcione como RadioButton, es necesario al momento de marcar un checkbox, recorrer la lista, desmarcar todos y luego marcar el que se seleccionó, por eso el truco.
Saludos.
#6
Posted 18 February 2016 - 05:00 PM
Es que para que funcione como RadioButton, es necesario al momento de marcar un checkbox, recorrer la lista, desmarcar todos y luego marcar el que se seleccionó, por eso el truco.
Saludos.
Hola genriquez
El truco consiste en solamente permitir un elemento marcado; si interceptamos la llamada OnItemClick y desmarcamos el ultimo elemento seleccionado, quedaria siempre un solo item marcado.
La unica forma de "romperlo", es si se permite seleccion multiple, seleccionar a varios y dar espacio; en ese caso no se que pasaria, habria que probarlo
La idea es evitar recorrer toda la lista en cada click
#7
Posted 19 February 2016 - 01:57 PM
Voy a probar sus recomendaciones y les cuento amigos.
#8
Posted 20 February 2016 - 03:56 PM
Muchas Gracias Delphius, Genriquez y Agustin por sus enseñanzas
de momento combinando sus ideas y códigos este me este sirviendo:
procedure TForm1.ListView1ItemChecked(Sender: TObject; Item: TListItem); var i: integer; begin for i:= ListView1.Items.Count-1 downto 0 do begin ListView1.Items[i].Checked:=false; end; ListView1.Items[Item.Index].Checked:=TRUE; ShowMessage(ListView1.Items[Item.Index].Caption); // ver lo que ha seleccionado, para pruebas end;
De momento este código me sirve, pero si hay alguna corrección o mejor manera de implementarlo les agradecería su observación.
#9
Posted 20 February 2016 - 04:39 PM
El codigo obviamente funciona bien, y me parece genial que estes abierto a criticas
1. Vuelvo a insistir con el tema de recorrer toda la lista, de cuantos elementos estamos hablando? El control TListView es muy bonito y versatil, pero es bastante lento
2. Si aun asi queres mantener este tipo de implementacion, yo haria la siguiente mejora:
ListView1.Items.BeginUpdate; try // codigo finally ListView1.Items.EndUpdate; end;
Al invocar al metodo BeginUpdate, le estamos diciendo al ListView que no se moleste en "actualizarse", o mejor dicho, re pintarse en cada propiedad que modificamos: las operaciones de renderizado de controles son bastante costosas.
La idea es modificar muchas propiedades y luego repintar el control solo una vez, al final; por eso se encapsula el bucle dentro de un bloque try-finally, para asegurarnos que siempre se invoque el metodo EndUpdate
3. Por que recorrer la lista en orden invertido? A mi me resulta mas confuso leer el codigo asi
4.
ListView1.Items[Item.Index].Checked:= True; // menos legible Item.Checked := True; // mas legible :)