Skip to main content

Implementing Drag-And-Drop Operations

  • 4 minutes to read

The ExpressVerticalGrid provides enhanced facilities for dragging rows. End-users can drag rows within the control to change their order and organize them into a tree. Also, rows can be dragged to the Customization Form and back to the control to hide and show them respectively. These drag and drop operations are implemented by the control and do not require coding. See the Customization Form Overview topic for details on enabling and disabling these drag and drop operations and the way that they are performed.

This topic describes implementing drag and drop between vertical grid controls and other controls.

Dragging Rows between Vertical Grid Controls

In this section, dragging rows between vertical grid controls is discussed. Create two TcxVerticalGrid controls. Set their DragMode property to dmAutomatic to enable automatic start of drag-and-drop operations. Populate one of them with rows as shown in the following screenshot (for more information on creating rows see the Creating a Tree-like Structure Of Rows topic):

Drag-and-drop functionality in this example is implemented by handling the OnDragOver and OnDragDrop events. The first event handler specifies whether the drag-and-drop operation is allowed and the OnDragDrop event handler implements the main functionality.

procedure TForm1.cxVerticalGrid2DragDrop(Sender, Source: TObject; X,
  Y: Integer);
var
  ADraggedRow, ARow, AParentRow, AChildRow: TcxCustomRow;
  I: Integer;
begin
//obtaining the TcxCustomRow instance corresponding to the dragged //row
  ADraggedRow := (Source as TcxvgDragRowObject).Row;
  if ADraggedRow.VerticalGrid = Sender then
    Exit;
//calculating hit information at the drop point and obtaining the row //at the drop point
  TcxVerticalGrid(Sender).HitTest.ReCalculate(Point(X, Y));
  AParentRow := TcxVerticalGrid(Sender).HitTest.HitRow;
//if the drop point is over a row...
  if Assigned(AParentRow) then
  begin
//then adding the dragged row as the target row's child
    ARow := TcxVerticalGrid(Sender).AddChild(AParentRow, TcxCustomRowClass(ADraggedRow.ClassType));
//copying the dragged row properties to the row created
    ARow.Assign(ADraggedRow);
  end
  else
  begin
//if the drop point is not over a row, then a new row added to the //root level of the vertical grid control
    ARow := TcxVerticalGrid(Sender).Add(TcxCustomRowClass(ADraggedRow.ClassType));
//copying the dragged row's properties to the row created
    ARow.Assign(ADraggedRow);
  end;
//if the dragged row has child rows
  if (ADraggedRow.HasChildren) then
  begin
    for I := 0 to ADraggedRow.Count - 1 do
    begin
//then the child collection structure is copied to the target //vertical grid control
      AChildRow := TcxVerticalGrid(Sender).AddChild(ARow, TcxCustomRowClass(ADraggedRow.Rows[I].ClassType));
      AChildRow.Assign(ADraggedRow.Rows[I]);
    end;
  end;
  ADraggedRow.Free;
end;
procedure TForm1.cxVerticalGrid2DragOver(Sender, Source: TObject; X,
  Y: Integer; State: TDragState; var Accept: Boolean);
begin
//determining whether the drag-and-drop operation is allowed
  Accept := (Source as TcxvgDragRowObject).Row.VerticalGrid <> Sender;
end;

The drag-and-drop operation’s result is shown in the following screenshot:

Dragging from the Vertical Grid Control to a VCL Control

This section discusses dragging rows from the vertical grid control to other VCL controls. The source vertical grid control is set up as in the previous section. The destination VCL control is a TListBox. Set the DragMode property of the vertical grid and the list box to dmAutomatic to enable automatic start of drag-and-drop operations.

The TListBox.OnDragOver event handler determines whether the dragged row can be dropped. The TListBox.OnDragDrop event handler implements the main functionality of this example. It determines the type (category, editor or multi editor) of the dragged row and, depending on that information, creates a string composed of the dragged row’s caption and row value.

procedure TForm1.ListBox1DragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
begin
//determining whether the drag-and-drop operation is allowed
  Accept := (Sender = ListBox1) and ((Source as TcxvgDragRowObject).Row.VerticalGrid = cxVerticalGrid1);
end;
procedure TForm1.ListBox1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
  ADraggedRow: TcxCustomRow;
  Str: String;
  I: Integer;
begin
//obtaining the dragged row
  ADraggedRow := (Source as TcxvgDragRowObject).Row;
//creating a string composed of the row caption and the row value
  if ADraggedRow is TcxCategoryRow then
    Str := TcxCategoryRow(ADraggedRow).Properties.Caption
  else
    if ADraggedRow is TcxEditorRow then
      Str := TcxEditorRow(ADraggedRow).Properties.Caption + ' : ' + TcxEditorRow(ADraggedRow).Properties.Value
    else
      if ADraggedRow is TcxMultiEditorRow then
      begin
        for I := 0 to TcxMultiEditorRow(ADraggedRow).Properties.Editors.Count - 1 do
        begin
          Str := Str + TcxMultiEditorRow(ADraggedRow).Properties.Editors[I].Caption + ' : ' +  TcxMultiEditorRow(ADraggedRow).Properties.Editors[I].Value;
          Str := Str + ' | ';
        end;
      end;
//adding the string created to the TListBox control
  TListBox(Sender).AddItem(Str, nil);
end;

The drag-and-drop operation result is shown in the following screenshot: