Back to Devexpress

VGridControlBase.ProcessDragRow Event

windowsforms-devexpress-dot-xtraverticalgrid-dot-vgridcontrolbase-34d5fafa.md

latest21.9 KB
Original Source

VGridControlBase.ProcessDragRow Event

Fires when a user drags a row.

Namespace : DevExpress.XtraVerticalGrid

Assembly : DevExpress.XtraVerticalGrid.v25.2.dll

NuGet Packages : DevExpress.Win.Navigation, DevExpress.Win.VerticalGrid

Declaration

csharp
public event ProcessDragRowEventHandler ProcessDragRow
vb
Public Event ProcessDragRow As ProcessDragRowEventHandler

Event Data

The ProcessDragRow event's data class is DragRowEventArgs. The following properties provide information specific to this event:

PropertyDescription
EffectGets or sets an effect available for the processed drag and drop operation.
RowGets the processed row. Inherited from RowEventArgs.
ScreenLocationGets a point representing the current mouse cursor position.

Remarks

The vertical grid allows custom row dragging to be implemented (for instance, dragging rows to external controls). This implies processing row drag and drop operations by handling a set of native drag-specific events that are introduced by the vertical grid.

These events occur in the following order:

For detailed information, see Dragging Rows.

Example

This example demonstrates how you can handle native drag specific grid events in order to combine a dragged row with the targeted one in a single multi-editor row. The example implies that an editor row dragged from the Customization Form can only be dropped onto the headers of editor or multi-editor rows. In a case when the target is a multi-editor row, a dropped row is inserted as a new row item for the target row. When dropping a row onto the header cell of the targeted editor row, both rows (dropped and target) are deleted from the grid and a multi-editor row with two row items is created instead. The created row items copy base row settings from the deleted rows. The position of the drop point inside the header cell of the target row (row item) affects the index of the new row item created for the dropped row.

Note that the example uses information from the BaseViewInfo object available via the VGridControlBase.ViewInfo property in order to properly calculate the targeted header cell’s bounds. The following picture illustrates the base view info notions used in the example.

The image below displays the process of handling row drag & drop operations using the code in this example.

If you want to split a multi-editor row into several editor rows you can use the code provided by the Dragging Rows topic.

csharp
using DevExpress.XtraVerticalGrid.Rows;
using DevExpress.XtraVerticalGrid.Events;

 private void vGridControl1_ProcessDragRow(object sender, DragRowEventArgs e) {
    VGridControl vGrid = (sender as VGridControl);
    // checking whether a row is dragged from the Customization Form
    if (!((vGrid.CustomizationForm != null) && (vGrid.CustomizationForm.PressedRow != null))) 
        return;
    // checking whether an editor row is dragged
    if (!(e.Row is EditorRow)) return;
    // obtaining information about a point under the mouse cursor
    VGridHitInfo hitInfo = vGrid.CalcHitInfo(vGrid.PointToClient(e.ScreenLocation)); 
    // checking whether a row is dragged over the Customization Form or over a category row
    if (!((hitInfo.HitInfoType != HitInfoTypeEnum.CustomizationForm) && (hitInfo.Row != null) && 
       (!(hitInfo.Row is CategoryRow)))) {
        e.Effect = RowDragEffect.None;
        return;
    }
    // obtaining specific custom information about the mouse cursor point
    PointInfo pInfo = GetPointInfo(hitInfo.Row, e.ScreenLocation); 
    // allowing row dropping is a point belongs to target row's header
    if (pInfo.IsContained) e.Effect = RowDragEffect.InsertBefore; 
    // restricting row dropping in the other case
    else e.Effect = RowDragEffect.None; 
}

private void vGridControl1_EndDragRow(object sender, EndDragRowEventArgs e) {
    VGridControl vGrid = (sender as VGridControl);
    // checking whether a row from the Customization Form is dropped
    if (!((vGrid.CustomizationForm != null) && (vGrid.CustomizationForm.PressedRow != null))) 
        return;
    // checking whether an editor row is dropped
    if (!(e.Row is EditorRow)) return;
    // obtaining information about a point under the mouse cursor
    VGridHitInfo hitInfo = vGrid.CalcHitInfo(vGrid.PointToClient(e.ScreenLocation)); 
    // checking whether a row is dropped onto the Customization Form or a category row
    if (!((hitInfo.HitInfoType != HitInfoTypeEnum.CustomizationForm) && 
        (hitInfo.Row != null) && (!(hitInfo.Row is CategoryRow)))) {
        e.Effect = RowDragEffect.None;
        return;
    }
    BaseRow targetRow = hitInfo.Row;
    // obtaining specific custom information about the mouse cursor point
    PointInfo pInfo = GetPointInfo(hitInfo.Row, e.ScreenLocation); 
    if (!(pInfo.IsContained)) {
        // if the header rectangle does not contain the drop point, 
        // a drop operation is not processed
        e.Effect = RowDragEffect.None; 
        return;
    }
    // specifying the cursor feedback for the processed drop operation
    e.Effect = RowDragEffect.InsertBefore; 
    // preserving children of the dropped row from being deleted
    if (e.Row.HasChildren) PreserveChildren(e.Row); 
    switch (targetRow.XtraRowTypeID){
        case 1: // the target is an editor row
            // preserving children of the target row from being deleted
            if (targetRow.HasChildren) PreserveChildren(targetRow); 
            // substituting the dropped and target rows with a new multi-editor row
            CreateMERow(e.Row, targetRow, pInfo.DroppedBefore); 
            break;
        case 2: // the target is a multi-editor row
            // inserting the dropped row as a new row item to the target multi-editor row
            InsertRowItem(e.Row, (targetRow as MultiEditorRow), pInfo.RowItemIndex, pInfo.DroppedBefore); 
            break;
    }
}

public Rectangle CalcHeaderCellRect(BaseRow row, int cellIndex){
    // this function uses grid's view info to properly calculate a rectangle 
    // occupied by the target row header cell
    VGridControl grid = row.Grid;
    // obtaining the header cell rectangle of the processed row item specified by the index
    Rectangle headerCellRect = (grid.ViewInfo[row].headerInfo.CaptionsInfo[cellIndex] 
      as RowCaptionInfo).CaptionRect;
    if (cellIndex == 0){
        // obtaining the number of row indent elements
        int rowIndentsCount = grid.ViewInfo[row].headerInfo.RowIndents.Count; 
        if (rowIndentsCount != 0) {
            // recalculating the rectangle for the first header cell 
            // since it visually comprises the last row indent element
            int leftPos = grid.ViewInfo[row].headerInfo.RowIndents[rowIndentsCount - 1].Bounds.Left;
            headerCellRect.Width += headerCellRect.X - leftPos;        
            headerCellRect.X = leftPos;
        }
    }
    return headerCellRect;
}

public struct PointInfo {
    public bool IsContained;
    public int RowItemIndex;
    public bool DroppedBefore;
}

public PointInfo GetPointInfo(BaseRow row, Point point){
    PointInfo pInfo = new PointInfo();
    // transforming screen coordinates of the cursor position to grid client ones
    Point mouseClientPoint = row.Grid.PointToClient(point); 
    // checking whether the mouse cursor is positioned 
    // within a particular header cell of the processed row
    for (int i = 0; i < row.RowPropertiesCount; i++){
        // obtaining the header cell rectangle of the processed row item
        Rectangle headerCellRect = CalcHeaderCellRect(row, i); 
        // checking whether the header cell rectangle contains the drop point
        // collecting information about the point if it is contained in a header cell rectangle
        if (headerCellRect.Contains(mouseClientPoint)) { 
            pInfo.IsContained = true;
            // calculating the middle point of the target row's header cell
            int headerCellMiddle = (headerCellRect.Left + headerCellRect.Right) / 2; 
            // calculating whether the dropped row should be inserted before the processed row item
            pInfo.DroppedBefore = (mouseClientPoint.X < headerCellMiddle) ? true : false; 
            // specifying the index of the row item whose header cell contains the point
            pInfo.RowItemIndex = i; 
            return pInfo;
        }
    }
    // the specified point does not belong to the target row's header
    pInfo.IsContained = false; 
    return pInfo;
}

public void PreserveChildren(BaseRow row){
    // this procedure moves children of the specified row to the top-level row collection 
    // and hides them in the Customization Form
    ArrayList rowList = new ArrayList(row.ChildRows);
    foreach (BaseRow childRow in rowList){
        childRow.Grid.MoveRow(childRow, childRow.Grid.Rows[0],true);
        childRow.Visible = false;
    }
}

public void CreateMERow (BaseRow source, BaseRow dest, bool droppedFirst){
    // this procedure creates a new multi-editor row with two row items initialized 
    //with corresponding rows' property values 
    MultiEditorRow meRow = new MultiEditorRow();
    MultiEditorRowProperties sourceRowItem = new MultiEditorRowProperties();
    CopyProperties(source.Properties, (sourceRowItem as RowProperties));
    MultiEditorRowProperties destRowItem = new MultiEditorRowProperties();
    CopyProperties(dest.Properties, (destRowItem as RowProperties));
    if (droppedFirst){
        meRow.PropertiesCollection.Add(sourceRowItem);
        meRow.PropertiesCollection.Add(destRowItem);
    }
    else {
        meRow.PropertiesCollection.Add(destRowItem);
        meRow.PropertiesCollection.Add(sourceRowItem);
    }
    // inserting the newly created multi-editor row to the target row's position
    if (dest.ParentRow != null){
        int index = dest.ParentRow.ChildRows.IndexOf(dest);
        dest.ParentRow.ChildRows.Insert(meRow, index);
    }
    else {
        int index = dest.Grid.Rows.IndexOf(dest);
        dest.Grid.Rows.Insert(meRow, index);
    }
    // deleting an instance of the target row
    dest.Dispose(); 
    // deleting an instance of the dropped row
    source.Dispose(); 
}

public void InsertRowItem (BaseRow source, MultiEditorRow dest, int itemIndex, 
bool droppedBefore){
    // this procedure creates a new row item, initializes it with the values of the dropped row
    // and inserts the item at a specific position within the target row
    MultiEditorRowProperties newRowItem = new MultiEditorRowProperties();
    CopyProperties(source.Properties, (newRowItem as RowProperties));
    if (droppedBefore) dest.PropertiesCollection.Insert(itemIndex, newRowItem);
    else {
        if (itemIndex == dest.PropertiesCollection.Count) 
          dest.PropertiesCollection.Add(newRowItem);
        else 
          dest.PropertiesCollection.Insert(itemIndex + 1, newRowItem);
    } 
    // deleting an instance of the dropped row
    source.Dispose(); 
}

public void CopyProperties(RowProperties source, RowProperties dest){
    // this procedure copies the public row properties of one row to another
   source.AssignTo(dest);
}
vb
Imports DevExpress.XtraVerticalGrid.Rows
Imports DevExpress.XtraVerticalGrid.Events

Private Sub VGridControl1_ProcessDragRow(ByVal sender As Object, _
ByVal e As DragRowEventArgs) Handles VGridControl1.ProcessDragRow
    Dim VGrid As VGridControl = CType(sender, VGridControl)
    ' checking whether a row is dragged from the Customization Form
    If Not ((Not VGrid.CustomizationForm Is Nothing) And _
        (Not VGrid.CustomizationForm.PressedRow Is Nothing)) Then Return
    ' checking whether an editor row is dragged
    If Not TypeOf (e.Row) Is EditorRow Then Return
    ' obtaining information about a point under the mouse cursor
    Dim hitInfo As VGridHitInfo = VGrid.CalcHitInfo(VGrid.PointToClient(e.ScreenLocation)) 
    ' checking whether a row is dragged over the Customization Form or over a category row
    If Not ((hitInfo.HitInfoType <> HitInfoTypeEnum.CustomizationForm) And _
       (Not hitInfo.Row Is Nothing) And (Not TypeOf (hitInfo.Row) Is CategoryRow)) Then
        e.Effect = RowDragEffect.None
        Return
    End If
    ' obtaining specific custom information about the mouse cursor point
    Dim PInfo As PointInfo = GetPointInfo(hitInfo.Row, e.ScreenLocation) 
    If PInfo.IsContained Then
        ' allowing row dropping is a point belongs to target row's header
        e.Effect = RowDragEffect.InsertBefore 
    Else : e.Effect = RowDragEffect.None ' restricting row dropping in the other case
    End If
End Sub

Private Sub VGridControl1_EndDragRow(ByVal sender As Object, _
ByVal e As EndDragRowEventArgs) Handles VGridControl1.EndDragRow
    Dim VGrid As VGridControl = CType(sender, VGridControl)
    ' checking whether a row from the Customization Form is dropped
    If Not ((Not VGrid.CustomizationForm Is Nothing) And _
       (Not VGrid.CustomizationForm.PressedRow Is Nothing)) Then Return
    ' checking whether an editor row is dropped
    If Not TypeOf (e.Row) Is EditorRow Then Return
    ' obtaining information about a point under the mouse cursor
    Dim hitInfo As VGridHitInfo = VGrid.CalcHitInfo(VGrid.PointToClient(e.ScreenLocation)) 
    ' checking whether a row is dropped onto the Customization Form or a category row
    If Not ((hitInfo.HitInfoType <> HitInfoTypeEnum.CustomizationForm) And _
       (Not hitInfo.Row Is Nothing) And (Not TypeOf (hitInfo.Row) Is CategoryRow)) Then
        e.Effect = RowDragEffect.None
        Return
    End If
    Dim TargetRow As BaseRow = hitInfo.Row
    ' obtaining specific custom information about the mouse cursor point
    Dim PInfo As PointInfo = GetPointInfo(hitInfo.Row, e.ScreenLocation) 
    If Not PInfo.IsContained Then
        ' if the header rectangle does not contain the drop point, 
        ' a drop operation is not processed
        e.Effect = RowDragEffect.None 
        Return
    End If
    ' specifying the cursor feedback for the processed drop operation
    e.Effect = RowDragEffect.InsertBefore 
    ' preserving children of the dropped row from being deleted
    If e.Row.HasChildren Then PreserveChildren(e.Row) 
    Select Case TargetRow.XtraRowTypeID
        Case 1 ' the target is an editor row
            ' preserving children of the target row from being deleted
            If TargetRow.HasChildren Then PreserveChildren(TargetRow) 
            ' substituting the dropped and target rows with a new multi-editor row
            CreateMERow(e.Row, TargetRow, PInfo.DroppedBefore) 
        Case 2 ' the target is a multi-editor row
            ' inserting the dropped row as a new row item to the target multi-editor row
            InsertRowItem(e.Row, CType(TargetRow, MultiEditorRow), _
              PInfo.RowItemIndex, PInfo.DroppedBefore) 
    End Select
End Sub

Public Function CalcHeaderCellRect(ByVal row As BaseRow, _
ByVal cellIndex As Integer) As Rectangle
    ' this function uses grid's view info to properly calculate a rectangle 
    ' occupied by the target row header cell
    Dim Grid As VGridControl = row.Grid
    ' obtaining the header cell rectangle of the processed row item specified by the index
    Dim HeaderCellRect As Rectangle = _
      CType(Grid.ViewInfo(row).headerInfo.CaptionsInfo(cellIndex), RowCaptionInfo).CaptionRect
    If cellIndex = 0 Then
        ' obtaining the number of row indent elements
        Dim RowIndentsCount As Integer = Grid.ViewInfo(row).headerInfo.RowIndents.Count 
        If RowIndentsCount <> 0 Then
            ' recalculating the rectangle for the first header cell 
            ' since it visually comprises the last row indent element
            Dim LeftPos As Integer = Grid.ViewInfo(row).headerInfo.RowIndents( _
              RowIndentsCount - 1).Bounds.Left
            HeaderCellRect.Width = HeaderCellRect.Width + (HeaderCellRect.X - LeftPos)
            HeaderCellRect.X = LeftPos
        End If
    End If
    Return HeaderCellRect
End Function

Public Structure PointInfo
    Public IsContained As Boolean
    Public RowItemIndex As Integer
    Public DroppedBefore As Boolean
End Structure

Public Function GetPointInfo(ByVal row As BaseRow, ByVal point As Point) As PointInfo
    Dim PInfo As New PointInfo()
    ' transforming screen coordinates of the cursor position to grid client ones
    Dim MouseClientPoint As Point = row.Grid.PointToClient(point) 
    ' checking whether the mouse cursor is positioned within a particular header cell 
    ' of the processed row
    Dim I As Integer
    For I = 0 To row.RowPropertiesCount - 1
        ' obtaining the header cell rectangle of the processed row item
        Dim HeaderCellRect As Rectangle = CalcHeaderCellRect(row, I) 
        ' checking whether the header cell rectangle contains the drop point
        ' collecting information about the point if it is contained in a header cell rectangle
        If HeaderCellRect.Contains(MouseClientPoint) Then 
            PInfo.IsContained = True
            ' calculating the middle point of the target row's header cell
            Dim headerCellMiddle As Integer = (HeaderCellRect.Left + HeaderCellRect.Right) / 2 
            ' calculating whether the dropped row should be inserted before the processed row item
            PInfo.DroppedBefore = IIf(MouseClientPoint.X < headerCellMiddle, True, False)  
            ' specifying the index of the row item whose header cell contains the point
            PInfo.RowItemIndex = I 
            Return PInfo
        End If
    Next
    PInfo.IsContained = False ' the specified point does not belong to the target row's header
    Return PInfo
End Function

Public Sub PreserveChildren(ByVal row As BaseRow)
    ' this procedure moves children of the specified row to the top-level row collection 
    ' and hides them in the Customization Form
    Dim RowList As New ArrayList(row.ChildRows)
    Dim ChildRow As BaseRow
    For Each ChildRow In RowList
        ChildRow.Grid.MoveRow(ChildRow, ChildRow.Grid.Rows(0), True)
        ChildRow.Visible = False
    Next
End Sub

Public Sub CreateMERow(ByVal source As BaseRow, _
ByVal dest As BaseRow, ByVal droppedFirst As Boolean)
    ' this procedure creates a new multi-editor row with 
    ' two row items initialized with corresponding rows' property values 
    Dim MeRow As New MultiEditorRow()
    Dim SourceRowItem As New MultiEditorRowProperties()
    CopyProperties(source.Properties, CType(SourceRowItem, RowProperties))
    Dim destRowItem As New MultiEditorRowProperties()
    CopyProperties(dest.Properties, CType(destRowItem, RowProperties))
    If droppedFirst Then
        MeRow.PropertiesCollection.Add(SourceRowItem)
        MeRow.PropertiesCollection.Add(destRowItem)
    Else
        MeRow.PropertiesCollection.Add(destRowItem)
        MeRow.PropertiesCollection.Add(SourceRowItem)
    End If
    ' inserting the newly created multi-editor row to the target row's position
    If Not dest.ParentRow Is Nothing Then
        Dim Index As Integer = dest.ParentRow.ChildRows.IndexOf(dest)
        dest.ParentRow.ChildRows.Insert(MeRow, Index)
    Else
        Dim index As Integer = dest.Grid.Rows.IndexOf(dest)
        dest.Grid.Rows.Insert(MeRow, Index)
    End If
    dest.Dispose() ' deleting an instance of the target row
    source.Dispose() ' deleting an instance of the dropped row
End Sub

Public Sub InsertRowItem(ByVal source As BaseRow, _
ByVal dest As MultiEditorRow, ByVal itemIndex As Integer, _
ByVal droppedBefore As Boolean)
    ' this procedure creates a new row item, initializes it with the values of the dropped row
    ' and inserts the item at a specific position within the target row
    Dim NewRowItem As New MultiEditorRowProperties()
    CopyProperties(source.Properties, CType(NewRowItem, RowProperties))
    If droppedBefore Then
        dest.PropertiesCollection.Insert(itemIndex, NewRowItem)
    ElseIf itemIndex = dest.PropertiesCollection.Count Then
        dest.PropertiesCollection.Add(NewRowItem)
    Else
        dest.PropertiesCollection.Insert(itemIndex + 1, NewRowItem)
    End If
    source.Dispose() ' deleting an instance of the dropped row
End Sub

Private Sub CopyProperties(ByVal source As RowProperties, ByVal dest As RowProperties)
   ' this procedure copies the public row properties of one row to another
   source.AssignTo(dest);
End Sub

See Also

StartDragRow

EndDragRow

VGridControlBase Class

VGridControlBase Members

DevExpress.XtraVerticalGrid Namespace