Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Problema con Multiselect en DbGrid (https://www.clubdelphi.com/foros/showthread.php?t=73423)

ElDioni 20-04-2011 13:20:31

Problema con Multiselect en DbGrid
 
Buenas tardes a todos,

me ha surgido un problema que no se como resolver, tengo en un formulario dos DbGrids, en uno de ellos tengo la opcion Multiselect=true para poder seleccionar varios registros, la idea es seleccionar los registros que quiero y arrastrarlos al segundo dbgrid, pero cuando tengo los registros seleccionados pincho en alguno de ellos para empezar el drag&drop y entonces solo queda marcado el registro donde he realizado el último click, hay alguna forma para hacer que, si pincho dentro de cualquiera de los registros seleccionados, no se desmarquen y pueda así arrastrarlos todos.

Espero que se haya entendido el problema.

Saludos.

ecfisa 20-04-2011 14:11:52

Hola ElDioni.

Revisá este enlace .

Un saludo.

ElDioni 20-04-2011 18:54:29

Gracias ecfisa, le echaré un vistazo.

Hasta el lunes, que me voy de Semana Santa, ya nos veremos a la vuelta.

Saludos.

ElDioni 16-05-2011 18:49:03

Buenas tardes,

hace unos días deje este hilo para ver que podría hacerse para solucionar el problema que planteé y ecfisa me direccionó a un hilo en donde gluglu había comentado algo (de forma bastante completa) que podría ayudarme, como soy un poco cepa me lié bastante con la solución propuesta por gluglu, así que me puse a crear una solución alternativa, la pongo por si a alguien le viene bien y aparte por si se podría producir algún error que yo no he tenido en cuenta y alguien me lo quiere corregir, de todas formas gracias a todos por vuestro tiempo.
Aquí está lo que he hecho:

-He creado dos variables, una que se llama QueFilas y otra
FilasSelecionadas.

En el evento OnCellClick del DbGrid pongo lo siguiente:
Código Delphi [-]
procedure TFrmMenuArt.DbGridOrdenesCellClick(Column: TColumn);
begin
FilasSeleccionadas:=DBGridOrdenes.SelectedRows.Count;
QueFilas:=QueFilas+DbGridOrdenes.DataSource.DataSet.FieldByName('NOrden').AsString+';';
end;
Tengo un botón de seleccionar todos los registros del DbGrid que hace lo siguiente:
Código Delphi [-]
procedure TFrmMenuArt.Seleccionartodo1Click(Sender: TObject);
begin
DBGridOrdenes.SelectedRows.Clear;
with DBGridOrdenes.DataSource.DataSet do
  begin
    First;
    DisableControls;
    try
      while not EOF do
      begin
        DBGridOrdenes.SelectedRows.CurrentRowSelected := True;
        Next;
      end;
      filasseleccionadas:=DbGridOrdenes.DataSource.DataSet.RecordCount;
    finally
      EnableControls;
    end;
  end;
end;
En el evento On MouseDown:
Código Delphi [-]
procedure TFrmMenuArt.DbGridOrdenesMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
temp:string;
w:integer;
gc: TGridCoord;
begin
if button=MBLeft then
  begin
    if FilasSeleccionadas>1 then
      begin
        if DbGridOrdenes.SelectedRows.CurrentRowSelected then
          begin
            gc:= DbGridOrdenes.MouseCoord(x, y);
            if FilasSeleccionadas=queryordenes.RecordCount then
              begin
                seleccionartodo1click(nil);
              end
            else
              begin
                temp:='';
                for w:=1 to length(QueFilas) do
                  begin
                    if QueFilas[w]=';' then
                      begin
                        DBGridOrdenes.DataSource.DataSet.Locate('NOrden',temp,[lopartialkey]);
                        DbGridOrdenes.SelectedRows.CurrentRowSelected := True;
                        temp:='';
                      end
                    else
                      begin
                        temp:=temp+QueFilas[w];
                      end;
                  end;
              end;
            if (gc.X > 0) AND (gc.Y > 0) then
              begin
                DbGridOrdenes.DataSource.DataSet.MoveBy(gc.Y - THackDBGrid(DbGridOrdenes).Row);
              end;
          end;
        end;
    DbGridOrdenes.BeginDrag(false,10);
  end;
end;
Y por último en el evento OnMouseUp tengo controlada mediante la variable pulsada, en el keypreview del form, si hay alguna tecla pulsada, para este caso controlo que sea 17 que es la tecla control.
Código Delphi [-]
procedure TFrmMenuArt.DbGridOrdenesMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if pulsada<>17 then QueFilas:='';
end;

Eso es todo, como siempre espero que alguno de los maestros me diga que lo que he hecho es una aberración, pero bueno, la intención es lo que cuenta.

Saludos y gracias de nuevo.

gluglu 16-05-2011 19:44:15

No he entrado al máximo detalle a analizar la solución que propones, pero a simple vista denoto algunos asuntos que no sé si funcionarán exactamente como tu lo prevés :

1. Utilizas RecordCount. Dependiendo de la base de datos, este valor es en la mayoría de las ocasiones muy falso, devolviendo valores que no suelen ser los reales. En el caso de Firebird al menos, se ha hablado en múltiples ocasiones en los foros que no se debería usar RecordCount.

2. No veo cómo solucionas el tema de pulsar la tecla Shift, que es el asunto principal del hilo que cree en su momento y que aparece al principio del Post. El principal problema es que la multiselección en el DBGrid estándar no está prevista con la tecla Shift, como en cualquier otro programa (como ejemplo se podría poner cualquier programa de correo electrónico).

Al pulsar el Shift deberían seleccionarse todos los registros desde el que actualmente estaba seleccionado hasta el que acabas de hacer click con la tecla shift pulsada.

3. No sé si es eficiente ejecutar Locate y MoveBy al tener el DBGrid abierto y con el DataSet asociado también abierto.

... sólo eran algunos comentarios propios a la solución propuesta, sin desmerecer ni la una ni la otra. ;)

ElDioni 17-05-2011 18:41:46

Buenas tardes gluglu,

La función del mouseup del dbgrid para que controle la tecla shift lo tenía puesto de la siguiente forma:

Código Delphi [-]
procedure TFrmMenuArt.DbGridOrdenesMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
w:integer;
begin
if pulsada<>17 then
  begin
    QueFilas:='';
    if button=MBLeft then
      begin
        if pulsada=16 then
          begin
            UltiRegOrd:=QueryOrdenes.RecNo;
            DbGridOrdenes.SelectedRows.Clear;
            for w:=PrimerRegOrd to UltiRegOrd do
              begin
                DbGridOrdenes.DataSource.DataSet.RecNo:=w;
                DbGridOrdenes.SelectedRows.CurrentRowSelected:=true;
                QueFilas:=QueFilas+DbGridOrdenes.DataSource.DataSet.FieldByName('NOrden').AsString+';';
              end;
            FilasSeleccionadas:=DbGridOrdenes.SelectedRows.Count;
          end
        else
          begin
            PrimerRegOrd:=QueryOrdenes.RecNo;
          end;
      end;
  end;
end;

Pero al hacerlo así se me mueve el listado y entonces empieza a volverse un poco loco, estoy dandole un poco de vueltas a ver si le saco punta.

Saludos.

ElDioni 18-05-2011 10:52:31

Buenos días,

al final he optado por la opción cobarde, he puesto el componente SMDBGrid que tiene la propiedad eoKeepSelection que deja seleccionados los registros seleccionados (valga la redundancia) aunque pinches fuera de uno de ellos, he tenido que poner un código en el OnMouseDown para que se deseleccionen los registros si he pinchado en alguno que no estuviera seleccionado.

Código Delphi [-]
procedure TFrmMenuArt.DBGridOrdenesMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if button=MBLeft then
  begin
    if (pulsada<>17)AND(pulsada<>16)then
      begin
        if DbGridOrdenes.SelectedRows.CurrentRowSelected=false then
          begin
            DbGridOrdenes.SelectedRows.Clear;
          end;
      end;
    DbGridOrdenes.BeginDrag(false,10);
    LblNOrden.Caption:=FrmMenuArt.QueryOrdenes.fieldbyname('NOrden').AsString;
  end;

end;

Si no había utilizado este componente antes es porque al poner el ReadOnly a true no te deja seleccionar una parte de texto de un registro con el que yo, posteriormente, hacía filtros por selección o excluyendo la selección, lo que he hecho es dejar el ReadOnly a false y en el OnKeyDown del SMDBGrid he controlado que no esté pulsado ni el control ni las mayusculas ni el alt y pongo el key:=0, así no se puede modificar el registro.

Gracias a todos por su tiempo.

Saludos.


La franja horaria es GMT +2. Ahora son las 12:41:27.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi