Skip to main content

DragRowEventArgs.Effect Property

Gets or sets an effect available for the processed drag and drop operation.

Namespace: DevExpress.XtraVerticalGrid.Events

Assembly: DevExpress.XtraVerticalGrid.v24.1.dll

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

Declaration

public RowDragEffect Effect { get; set; }

Property Value

Type Description
RowDragEffect

A RowDragEffect enumeration value representing the pointer feedback indicating what happens if the mouse is released at any given moment.

Available values:

Name Description
None

RowDragEffect_None

Specifies the pointer feedback indicating that none of the predefined effects is allowed for the dragged row if the mouse is released at a given moment during a drag operation.

InsertBefore

RowDragEffect_InsertBefore

Specifies the pointer feedback indicating that the dragged row is allowed to be inserted before a target row if the mouse is released at a given moment during a drag operation.

MoveChild

RowDragEffect_MoveChild

Specifies the pointer feedback indicating that the dragged row is allowed to be inserted as a child of a target row if the mouse is released at a given moment during a drag operation.

MoveToEnd

RowDragEffect_MoveToEnd

Specifies the pointer feedback indicating that the dragged row is allowed to be inserted after the last row in the VGridControlBase.Rows collection if the mouse is released at a given moment during a drag operation.

InsertAfter

A row is inserted after another row.

Remarks

The Effect property is useful for providing visual feedback during a drag operation. By setting this property you can specify the icon displayed as the pointer during a drag and drop operation and enable the corresponding action for the dragged row. In this way, pointer feedback provided by this property indicates what will happen if the mouse is released at any given moment during row dragging.

In a handler for the VGridControlBase.ProcessDragRow event you can use this property to change the pointer feedback continually as the user moves the dragged row. For example, if the pointer is moved over an object that cannot accept a drop, the pointer can be changed to the “not allowed” symbol specified by the RowDragEffect.None value.

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.

Native_DragDrop_ViewInfos

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

anim_NativeDragDrop

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

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);
}
See Also