Я полагаю, что ваше q вызвано тем фактом, что хотя TDBCtrlGrid имеет свойство PanelIndex
, которое сообщает вам, какая из виртуальных панелей сетки активна (т. Е. Является той, для текущей строки в наборе данных), это не не меняйте при перемещении мыши, например, во время операции перетаскивания. Тем не менее, нетрудно рассчитать это самостоятельно, как показано ниже.
Height
и Width
TDBCtrlGrid являются точными кратными RowCount
и ColCount
. В простом случае ColCount = 1 несложно вычислить, какая строка содержит заданную координату Y в сетке:
function TForm1.PanelIndexFromYPos(Y : Integer) : Integer;
var
PanelHeight : Integer;
begin
PanelHeight := DBCtrlGrid1.ClientHeight div DBCtrlGrid1.RowCount;
Result := Y div PanelHeight;
end;
(очевидно, это для простого случая одного столбца goVertical
ориентированная сетка, но ее будет легко обобщить)
Теперь TBDCtrlGrid EndDrag
(и MouseOver
) сообщает вам координату Y TPoint, где заканчивается операция перетаскивания, так что вы можете использовать эту PanelIndexFromYPos
функция, чтобы сказать вам, на какой индекс строки пользователь уронил перетащенную строку. Как объяснил @KenWhite, вам необходимо изменить порядок расположения CDS, чтобы отразить новую позицию, в которой должна находиться перетаскиваемая строка. Это легко сделать, если в вашем CDS есть поле DisplayIndex, представляющее позицию строки данной записи в CDS и CDS имеет активный индекс в этом поле. Переупорядочение записей CDS представляет собой непростую задачу, как будет видно из следующего примера проекта.
TForm1 = class(TForm)
CDS1: TClientDataSet;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
DBCtrlGrid1: TDBCtrlGrid; // Note: DragMode set to dmManual;
DBText1: TDBText; // In the DBCtrlGrid
DBText2: TDBText;
DBText3: TDBText;
edSourceIndex: TEdit;
edDestIndex: TEdit;
btnTest: TButton;
Memo1: TMemo;
Label1: TLabel;
procedure FormCreate(Sender: TObject);
procedure DBCtrlGrid1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure DBCtrlGrid1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
procedure DBCtrlGrid1DragDrop(Sender, Source: TObject; X, Y: Integer);
procedure btnTestClick(Sender: TObject);
private
procedure MoveRow(SourceIndex, DestIndex : Integer);
procedure LogMove(OldValue, NewValue: Integer);
procedure ShowPanelInfo(Y: Integer);
protected
function PanelIndexFromYPos(Y : Integer) : Integer;
public
SourceIndex : Integer; // the DbCtrlGrid PanelIndex of the row being dragged
DestIndex : Integer; // the PanelIndex where the row is dropped
end;
[...]
function TForm1.PanelIndexFromYPos(Y : Integer) : Integer;
var
PanelHeight : Integer;
begin
PanelHeight := DBCtrlGrid1.ClientHeight div DBCtrlGrid1.RowCount;
Result := Y div PanelHeight;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
AField : TField;
begin
// Create the fields for the CDS
AField := TIntegerField.Create(Self);
AField.FieldName := 'ID';
AField.DataSet := CDS1;
// This DisplayIndex field will be used to determine which row number in
// the DBCtrlGrid will occupy, by indexing the CDS on this field
AField := TIntegerField.Create(Self);
AField.FieldName := 'DisplayIndex';
AField.DataSet := CDS1;
AField := TStringField.Create(Self);
AField.FieldName := 'Name';
AField.Size := 20;
AField.DataSet := CDS1;
CDS1.CreateDataSet;
// Add some data which will appear in the grid in reverse-alphabetical order
CDS1.InsertRecord([1, 3, 'A']);
CDS1.InsertRecord([2, 2, 'B']);
CDS1.InsertRecord([3, 1, 'C']);
CDS1.InsertRecord([4, 0, 'D']);
CDS1.IndexFieldNames := 'DisplayIndex';
end;
procedure TForm1.DBCtrlGrid1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then begin
SourceIndex := PanelIndexFromYPos(Y);
DBCtrlGrid1.BeginDrag(False);
end;
end;
procedure TForm1.DBCtrlGrid1DragOver(Sender, Source: TObject; X,
Y: Integer; State: TDragState; var Accept: Boolean);
begin
Accept := True;
end;
procedure TForm1.DBCtrlGrid1DragDrop(Sender, Source: TObject; X,
Y: Integer);
begin
ShowPanelInfo(Y);
DestIndex := PanelIndexFromYPos(Y);
MoveRow(SourceIndex, DestIndex);
end;
procedure TForm1.MoveRow(SourceIndex, DestIndex : Integer);
var
BM : TBookMark;
Index : Integer;
procedure SetCDSIndex(Value : Integer);
var
OldValue : Integer;
begin
OldValue := CDS1.FieldByName('DisplayIndex').AsInteger;
CDS1.Edit;
CDS1.FieldByName('DisplayIndex').AsInteger := Value;
CDS1.Post;
LogMove(OldValue, Value);
end;
begin
if SourceIndex = DestIndex then exit;
CDS1.DisableControls;
try
if CDS1.FindKey([SourceIndex]) then begin
BM := CDS1.GetBookmark; // This is to keep track of the dragged row without needing to
// keep track of its (changing) DisplayIndex
if SourceIndex > DestIndex then begin
// i.e. we're moving the dragged row up in the grid
// so starting with the row above it we move the rows upwards
// eventually leaving a gap to drop the dragged row into
Index := SourceIndex - 1;
while Index >= DestIndex do begin
if CDS1.FindKey([Index]) then begin
SetCDSIndex(Index + 1);
end;
Dec(Index);
end;
end
else begin
// i.e. we're moving the dragged row down in the grid
// so starting with the row below it we move the rows upwards
// eventually leaving a gap to drop the dragged row into
Index := SourceIndex + 1;
while Index <= DestIndex do begin
if CDS1.FindKey([Index]) then begin
SetCDSIndex(Index - 1);
end;
Inc(Index);
end;
end;
end;
CDS1.GotoBookMark(BM);
if CDS1.FieldByName('DisplayIndex').AsInteger = SourceIndex then begin
SetCDSIndex(DestIndex);
end;
CDS1.FreeBookmark(BM); // should really have it's own try...finally but hey!
finally
CDS1.EnableControls;
end;
end;
procedure TForm1.LogMove(OldValue, NewValue : Integer);
begin
Memo1.Lines.Add(Format('Name: %s Old: %d New: %d ', [CDS1.FieldByName('Name').AsString, OldValue, NewValue]));
end;
procedure TForm1.ShowPanelInfo(Y : Integer);
begin
Label1.Caption := Format('y: %d panelindex: %d', [Y, PanelIndexFromYPos(Y)]);
end;
procedure TForm1.btnTestClick(Sender: TObject);
begin
// For debugging, to test mving rows without needing to drag/drop
MoveRow(StrToInt(edSourceIndex.Text), StrToInt(edDestIndex.Text));
end;
end.