Ir al contenido


Foto

Usar Checkbox como Radiobutton en Listview


  • Por favor identifícate para responder
8 respuestas en este tema

#1 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 259 mensajes

Escrito 18 febrero 2016 - 09:02

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. :)


  • 0

#2 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 18 febrero 2016 - 09:28

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,


  • 0

#3 genriquez

genriquez

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 539 mensajes
  • LocationCali, Colombia

Escrito 18 febrero 2016 - 01:29

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.


  • 0

#4 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 18 febrero 2016 - 03:36

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


delphi
  1. procedure TForm1.ListView1ItemChecked(Sender: TObject; Item: TListItem);
  2. begin
  3. if Item.Checked then
  4. ShowMessageFmt('Item %d %s checked', [Item.Index, Item.Caption])
  5. else
  6. ShowMessageFmt('Item %d %s unchecked', [Item.Index, Item.Caption]);
  7. 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 


  • 1

#5 genriquez

genriquez

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 539 mensajes
  • LocationCali, Colombia

Escrito 18 febrero 2016 - 04:31

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.


  • 1

#6 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 18 febrero 2016 - 05:00

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


  • 0

#7 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 259 mensajes

Escrito 19 febrero 2016 - 01:57

Voy a probar sus recomendaciones y les cuento amigos.


  • 0

#8 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 259 mensajes

Escrito 20 febrero 2016 - 03:56

Muchas Gracias Delphius, Genriquez y Agustin por sus enseñanzas  :)  :)  de momento combinando sus ideas y códigos este me este sirviendo:


php
  1. procedure TForm1.ListView1ItemChecked(Sender: TObject; Item: TListItem);
  2. var i: integer;
  3. begin
  4. for i:= ListView1.Items.Count-1 downto 0 do
  5. begin
  6.     ListView1.Items[i].Checked:=false;
  7.   end;
  8.  
  9. ListView1.Items[Item.Index].Checked:=TRUE;
  10. ShowMessage(ListView1.Items[Item.Index].Caption);   // ver lo que ha seleccionado, para pruebas

De momento este código me sirve, pero si hay alguna corrección o mejor manera de implementarlo les agradecería su observación.  :)


  • 1

#9 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 20 febrero 2016 - 04:39

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:


delphi
  1. ListView1.Items.BeginUpdate;
  2. try
  3. // codigo
  4. finally
  5. ListView1.Items.EndUpdate;
  6. 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.


php
  1. ListView1.Items[Item.Index].Checked:= True; // menos legible
  2.  
  3. Item.Checked := True; // mas legible :)


  • 1




IP.Board spam blocked by CleanTalk.