如何拖放DBGrid里的记录? 强烈关注 (50分)

S

samcrm

Unregistered / Unconfirmed
GUEST, unregistred user!
查了很多资料,都没有提及DBGrid内整条记录拖放的实现方法,包括InforPower的wwDBGrid也没有实现这个功能。
希望大家讨论一下:
用户希望能通过鼠标拖放改变记录顺序,例如想把第四条记录拖到第一条的位置。
如何实现?欢迎大家有招出招,无招帮顶。
 
顶一个先
 
TStringGrid 和dbgrid一样

unit OtherSort;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Grids, ExtCtrls, Buttons, StdCtrls,dbtables,dbgrids,db, Wwdbigrd, Wwdbgrid;

type
TOtherSortFrm = class(TForm)
Panel1: TPanel;
StringGrid1: TStringGrid;//显示数据库中要排序的表的字段名及其序号
Panel2: TPanel;
StringGrid2: TStringGrid;//从StringGrid1拉过来的要排序的字段及其序号
Panel3: TPanel;
Panel4: TPanel;
SpeedButton1: TSpeedButton;//排序
SpeedButton2: TSpeedButton;//取消
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure StringGrid2SelectCell(Sender: TObject; ACol, ARow: Integer;
var CanSelect: Boolean);
procedure StringGrid1DblClick(Sender: TObject);
procedure StringGrid2DblClick(Sender: TObject);
procedure SpeedButton2Click(Sender: TObject);
procedure SpeedButton1Click(Sender: TObject);
private
{ Private declarations }

public
{ Public declarations }
FQuery:TQuery;
FDbGRid:TwwDBGrid;
procedure DeleteRow(Row:integer;StringGrid: TStringGrid);
Function GetFieldName(FindName:string):string;
Function GetKeyFieldName(FindName:string):string;
end;
procedure P_OtherSort( Query:TQuery;DbGRid:TwwDBGrid);
var
OtherSortFrm: TOtherSortFrm;

implementation

{$R *.DFM}
procedure P_OtherSort( Query:TQuery;DbGRid:TwwDBGrid);
var dlg:TOtherSortFrm;
begin
try
dlg:=TOtherSortFrm.Create(nil);
dlg.FDbgrid:=DBGrid;
dlg.FQuery:=Query;
dlg.ShowModal;
finally
dlg.Free;
end;
end;

procedure TOtherSortFrm.FormCreate(Sender: TObject);
begin
StringGrid1.Cells[0,0]:=' 序号';
StringGrid1.Cells[1,0]:=' 字段名';
StringGrid2.Cells[0,0]:=' 序号';
StringGrid2.Cells[1,0]:=' 字段名';
StringGrid2.Cells[2,0]:='排序条件';
end;

procedure TOtherSortFrm.FormShow(Sender: TObject);
var i:integer;
RNum:integer;
str:string;
begin
for i:=0 to FDbGrid.GetColCount -2 do
begin
if (FDbGrid.Fields.FieldKind = fkData) or (FDbGrid.Fields.FieldKind = fkLookup) then
begin
//判断是否还是查找字段
if (FDbGrid.Fields.FieldKind = fkLookup) then
begin
str:=FDbGrid.Fields.KeyFields;
if FDbGrid.DataSource.DataSet.FieldByName(str).FieldKind = fkLookup then continue;
end;

if StringGrid1.Cells[0,1]='' then RNum:=1
else
begin
RNum:=StringGrid1.RowCount;
StringGrid1.RowCount:=StringGrid1.RowCount + 1;
end;
StringGrid1.Cells[0,RNum]:=inttostr(RNum);
StringGrid1.Cells[1,RNum]:=trim(FDbGrid.Columns.DisplayLabel);
end;
end;
end;

procedure TOtherSortFrm.DeleteRow(Row:integer;StringGrid: TStringGrid);
var i:integer;
begin
//大于2时要删除行
if StringGrid.RowCount > 2 then
begin
for i:=Row to StringGrid.RowCount - 1 do
begin
//行移动
StringGrid.Rows:=StringGrid.Rows[i+1];
end;
StringGrid.RowCount:=StringGrid.RowCount - 1;
end
else StringGrid.Rows[row].Clear;

end;
procedure TOtherSortFrm.StringGrid2SelectCell(Sender: TObject; ACol,
ARow: Integer; var CanSelect: Boolean);
var RNum:integer;
begin
//当单击第三列时改变升降序
if ACol = 2 then
begin
if StringGrid2.Cells[0,ARow]='' then exit;

if StringGrid2.Cells[2,ARow]='↑' then StringGrid2.Cells[2,ARow]:='↓'
else StringGrid2.Cells[2,ARow]:='↑' ;
end;
end;

procedure TOtherSortFrm.StringGrid1DblClick(Sender: TObject);
var RNum:integer;
begin
if StringGrid1.Cells[0,1]='' then exit;
//双击时移动行
if StringGrid2.Cells[0,1]='' then RNum:=1
else
begin
RNum:=StringGrid2.RowCount;
StringGrid2.RowCount:=StringGrid2.RowCount + 1;
end;
StringGrid2.Cells[0,RNum]:=StringGrid1.Cells[0,StringGrid1.row];
StringGrid2.Cells[1,RNum]:=StringGrid1.Cells[1,StringGrid1.row];
StringGrid2.Cells[2,RNum]:='↑';
DeleteRow(StringGrid1.row,StringGrid1);
end;

procedure TOtherSortFrm.StringGrid2DblClick(Sender: TObject);
var RNum:integer;
begin
if StringGrid2.col = 2 then exit;
//双击时移动行
if StringGrid2.Cells[0,1]='' then exit;
if StringGrid1.Cells[0,1]='' then RNum:=1
else
begin
RNum:=StringGrid1.RowCount;
StringGrid1.RowCount:=StringGrid1.RowCount + 1;
end;
StringGrid1.Cells[0,RNum]:=StringGrid2.Cells[0,StringGrid2.row];
StringGrid1.Cells[1,RNum]:=StringGrid2.Cells[1,StringGrid2.row];
DeleteRow(StringGrid2.row,StringGrid2);
end;

procedure TOtherSortFrm.SpeedButton2Click(Sender: TObject);
begin
close;
end;
Function TOtherSortFrm.GetFieldName(FindName:string):string;
var i:integer;
begin
for i:=0 to FDbGrid.GetColCount -2 do
begin
if trim(FDbGrid.Columns.DisplayLabel) = FindName then
begin
result:= FDbGrid.Columns.FieldName;
break;
end;
end;
end;
Function TOtherSortFrm.GetKeyFieldName(FindName:string):string;
var i:integer;
begin
result:='';
for i:=0 to FDbGrid.GetColCount -2 do
begin
if trim(FDbGrid.Columns.DisplayLabel) = FindName then
begin
result:= FDbGrid.Fields.KeyFields;;
break;
end;
end;
end;
procedure TOtherSortFrm.SpeedButton1Click(Sender: TObject);
var FOrder:string;
i:integer;
str:string;
p:integer;
FieldName:string;
begin
FOrder:=' ORDER BY ';
for i:=1 to StringGrid2.RowCount - 1 do
begin
FieldName:=GetFieldName(StringGrid2.Cells[1,i]);
//判断是否是查找字段
if FDbGrid.DataSource.DataSet.FieldByName(FieldName).FieldKind = fkLookup then
FOrder:=FORder + GetKeyFieldName(StringGrid2.Cells[1,i])
else
FOrder:=FORder + FieldName;

if StringGrid2.Cells[2,i] = '↑' then FOrder:=FORder+' ASC,'
else FOrder:=FORder+' DESC,';
end;
Forder:=Copy(Forder,0,length(Forder)-1);//去掉最后的','
str:=StrUpper(pchar(FQuery.SQL.Text));
str:=copy(str,0,length(str)-2);
p:=pos('ORDER BY',str);
if p>0 then str:=copy(str,0,p-1);
FQuery.DisableControls;
FQuery.close;
FQuery.sql.Text:=str+FOrder;
FQuery.open;
FQuery.EnableControls;
close;
end;

end.
 
好兄弟,是不是麻烦了点。
我曾经想过将DBGrid的内容拷贝到StringGrid中,这样StringGrid本身就可以上下拖动记录。
然后再将拖好后的StringGrid内容覆盖到数据库中。如此代码更简洁,只需写拷贝的代码。
我想看看能不能有更好的办法,只用DNGrid控件。
提示:
1、设置DBGrid的dgRowSelect属性为True,可以整行选择
2、设置DBGrid的DragMode属性为dmAutoMatic,可以拖;
3、在DBGrid的DragOver事件中写 Accept:=True; 可以接纳拖放。
完成上面3步,已经可以“拖”。

但是!!!
如何放!
 
我的思路是:
第四条记录拖到第一条记录位置,松开鼠标,此时DBGrid的数据源在第一条记录位置插入新记录,其各字段值从被拖的记录获得,然后delete第四条记录,然后Post。
也许我的想法不是最好的,大家看看怎么做最好?
 
同意SAMCRM,但先POST,再删除第四记录,再定位到新记录,
做这些时再加禁止显示语句
 
DBGrid本身可以实现列拖动,为什么不能实现行拖动?
 
多人接受答案了。
 
顶部