通过单击按钮更改 TGridPanel 中的行顺序

Change the order of rows in TGridPanel by button click

我喜欢通过单击按钮来更改 TGridPanel 中行的顺序。 Gridpanel 行是动态创建的,并包含一个带有手动停靠表单的面板。该表单有自己的编辑组件和一个带有当前行索引的标签。 最好的方法是这样的:

  1. 通过单击标记该行
  2. 单击“向上”或“向下”按钮。
  3. 所选行移动up/down。
  4. 停靠形式中行的索引发生变化。

这是我的尝试:

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    GridPanel1->RowCollection->Clear();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::BitBtn_StepAddClick(TObject *Sender)
{
    GridPanel1->RowCollection->BeginUpdate();

    if (GridPanel1->RowCollection->Count > 0)
        GridPanel1->Height = GridPanel1->Height + 156;

    TRowItem * RowItem = GridPanel1->RowCollection->Add();
    RowItem->SizeStyle = ssAbsolute;
    RowItem->Value     = 156;

    TPanel * Panel2 = new TPanel(this);
    Panel2->Parent = GridPanel1;
    Panel2->Color  = clWhite;
    Panel2->Name   = "Panel" + IntToStr(GridPanel1->RowCollection->Count) + "2";
    Panel2->Align  = alClient;
    Panel2->AlignWithMargins = false;

    TForm2 * Form2 = new TForm2(this, GridPanel1->RowCollection->Count);
    Form2->ManualDock(Panel2, Panel2, alClient);
    Form2->Show();

    BitBtn_StepDelete->Enabled = true;

    GridPanel1->RowCollection->EndUpdate();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::BitBtn_StepDeleteClick(TObject *Sender)
{
    // at the moment this button deletes the last row in GridPanel. But it would be fine to select a row by clicking it and delete the selected one.
    // After deleting it, the titles of the manually docked forms should change
    GridPanel1->RowCollection->BeginUpdate();

    GridPanel1->ControlCollection->Delete(GridPanel1->ControlCollection->Count - 1);
    GridPanel1->RowCollection->Delete(GridPanel1->RowCollection->Count - 1);

    if (GridPanel1->RowCollection->Count > 0)
        GridPanel1->Height = GridPanel1->Height - 156;
    else
        BitBtn_StepDelete->Enabled = false;

    GridPanel1->RowCollection->EndUpdate();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::BitBtn_StepInsertClick(TObject *Sender)
{
    // Select a row by clicking it and then add a new row before
}
//---------------------------------------------------------------------------

void __fastcall TForm1::BitBtn_StepUpClick(TObject *Sender)
{
    // Select a row by clicking it and move it up by this button click
}
//---------------------------------------------------------------------------

void __fastcall TForm1::BitBtn_StepDownClick(TObject *Sender)
{
    // Select a row by clicking it and move it down by this button click
}
//---------------------------------------------------------------------------

有人知道吗?

这是 MoveUp 按钮点击处理程序的 Delphi 实现。它取决于保存当前选定行索引的变量 SelRowId: integer,如果选择了 none,则为 -1。

它不会移动行,而是将内容(例如面板)从一个单元格移动到另一个单元格。

procedure TForm39.MoveUpBtnClick(Sender: TObject);
var
  NewRowId: integer;
begin
  GridPanel1.RowCollection.BeginUpdate;

  if InRange(SelRowId, 1, GridPanel1.ControlCollection.Count-1) then
  begin
    NewRowId := SelRowId - 1;
    GridPanel1.ControlCollection.ControlItems[0,SelRowId].Row := NewRowId;
    SelRowId := NewRowId;
  end;

  GridPanel1.RowCollection.EndUpdate;
end;

MoveDown程序在其他方面类似,但SelRowId的测试是

if InRange(SelRowId, 0, GridPanel1.ControlCollection.Count-2)

NewRowId 的赋值是

`NewRowId := SelRowId + 1;`

SelRowId必须初始化为-1,并在没有选择面板时设置为-1。

我假设在我的测试应用程序中单击面板...

// Clicking a panel
// - deselects the panel if it was previously selected
// - deselects any other previously selected panel in preparation to:
// - selects the panel if it was not previously selected

在我的测试应用程序中,我分两步获得选定的面板行:

  1. 通过ControlCollection.IndexOf(panel)

    获取面板索引
  2. 从 ControlCollection[indx] 中获取行

    var
      indx: integer;
      Panel: TPanel;

    Panel := Sender as TPanel;
    {...}
    indx := TGridPanel(Panel.Parent).ControlCollection.IndexOf(Panel);
    SelRowId := TGridPanel(Panel.Parent).ControlCollection[indx].Row;

我的测试项目的完整实现在这里:

implementation

{$R *.dfm}
uses Math;

procedure TForm39.FormCreate(Sender: TObject);
begin
  SelRowId := -1;
end;

procedure TForm39.MoveUpBtnClick(Sender: TObject);
var
  NewRowId: integer;
begin
  GridPanel1.RowCollection.BeginUpdate;

  if InRange(SelRowId, 1, GridPanel1.ControlCollection.Count-1) then
  begin
    NewRowId := SelRowId - 1;
    GridPanel1.ControlCollection.ControlItems[0,SelRowId].Row := NewRowId;
    SelRowId := NewRowId;
  end;

  GridPanel1.RowCollection.EndUpdate;
end;

procedure TForm39.MoveDnBtnClick(Sender: TObject);
var
  NewRowId: integer;
begin
  GridPanel1.RowCollection.BeginUpdate;

  if InRange(SelRowId, 0, GridPanel1.ControlCollection.Count-2) then
  begin
    NewRowId := SelRowId + 1;
    GridPanel1.ControlCollection.ControlItems[0,SelRowId].Row := NewRowId;
    SelRowId := NewRowId;
  end;

  GridPanel1.RowCollection.EndUpdate;
end;

procedure TForm39.AddStepBtnClick(Sender: TObject);
var
  NewRow: TRowItem;
  P: Tpanel;
begin
  GridPanel1.RowCollection.BeginUpdate;

  NewRow := GridPanel1.RowCollection.Add;
  GridPanel1.Height := GridPanel1.Height + 50;
  NewRow.SizeStyle := ssAbsolute;
  NewRow.Value := 50;

  P := Tpanel.Create(self);
  P.Caption := 'Panel '+IntToStr(GridPanel1.RowCollection.Count);
  P.Align := alClient;
  P.AlignWithMargins := False;
  P.Parent := GridPanel1;
  P.ParentBackground := False;
  P.ParentColor := False;
  P.Color := Random(256) shl 16 + Random(256) shl 8 + Random(256);
  P.OnClick := PanelClick;

  GridPanel1.RowCollection.EndUpdate;
end;

// Clicking a panel
// - selects the panel if it was not previously selected
// - deselects the panel if it was previously selected
// - deselects any other previously selected panel
procedure TForm39.PanelClick(Sender: TObject);
var
  indx: integer;
  Panel: TPanel;
begin
  Panel := Sender as TPanel;

  // previously selected panel
  if Assigned(SelPanel) then
    SelPanel.Color := SavedColor; // reset its color
  if SelPanel = Panel then        // a second click unselects
  begin
    SelPanel := nil;
    SelRowId := -1;
    Exit;
  end;

  SavedColor := Panel.Color;  // save newly selected panels color
  Panel.Color := clRed;       // set selected color
  SelPanel := Panel;          // set selected panel

  indx := TGridPanel(Panel.Parent).ControlCollection.IndexOf(Panel);
  SelRowId := TGridPanel(Panel.Parent).ControlCollection[indx].Row;
end;