VerticalGrid as the Target of Drag and Drop

  • 10 minutes to read

This topic shows how to customize a vertical grid control so it can serve as a target for OLE drag and drop operations. You can use this topic’s code sample to apply styles to individual rows using drag and drop. A general overview for implementing OLE drag and drop can be found in OLE Drag and Drop Overview.

Drag Styles onto Vertical Grid Rows

The sample in this topic involves the customization of two controls. A list box control will serve as the drag and drop source, the VGridControl will accept the dragged values. Actually, this sample performs the following tasks.

  • Creates and customizes two appearances (AppearanceObject objects).
  • Adds two items to the list box control that is the drag and drop source. Item captions must be the same as appearance names.
  • Performs custom painting of items in the list box.
  • Customizes the list box to be the OLE drag and drop source. Specify item captions as the drag data.
  • Customizes the vertical grid control to be the target for OLE Drag and Drop operations. Allows dropping only onto row headers or cells. The appearance whose name is specified by the drag data must be used to paint the target row.

The grid’s styles can be initialized together with list box control items. This can be performed in the form’s Load event handler as demonstrated in the code below. Note that the list box control’s DrawMode property is set to DrawMode.OwnerDrawVariable to force the control to use the MeasureItem and DrawItem events to specify the size of its items and paint them. Also, you need to set the vertical grid control’s AllowDrop property to true to allow dropping onto the control.

AppearanceObject[] appearanceCollection;
private void Form1_Load(object sender, System.EventArgs e) {
   // ...
   AppearanceObject appearanceBlue = new DevExpress.Utils.AppearanceObject("Blue appearance");
   appearanceBlue.BackColor = Color.LightGray;
   appearanceBlue.ForeColor = Color.Black;
   appearanceBlue.Font = new Font(appearanceBlue.Font, FontStyle.Italic);
   AppearanceObject appearanceGreen = new DevExpress.Utils.AppearanceObject("Green appearance");
   appearanceGreen.BackColor = Color.Yellow;
   appearanceGreen.ForeColor = Color.Black;
   appearanceGreen.Font = new Font("Tahoma", 10, FontStyle.Bold);

   appearanceCollection = new DevExpress.Utils.AppearanceObject[]{appearanceBlue, appearanceGreen};

   // Initializing the list box.
   listBox1.Items.Add("Blue appearance");
   listBox1.Items.Add("Green appearance");
   listBox1.DrawMode = DrawMode.OwnerDrawVariable;
   // Enabling dropping onto the vertical grid.
   vGridControl1.AllowDrop = true;
}

The next step is to specify the size of items and paint them using the defined styles. The list box’s MeasureItem and DrawItem events are used for this purpose. The MeasureItem event handler sets the processed item’s height to the height of the “Style Sample” string if it was painted using the font set by the corresponding style. The DrawItem event handler paints the processed item using the corresponding style’s settings.

private void listBox1_MeasureItem(object sender, System.Windows.Forms.MeasureItemEventArgs e) {
   AppearanceObject appearance = appearanceCollection[e.Index];
   e.ItemHeight = (int) e.Graphics.MeasureString("Style Sample", appearance.Font).Height;
}

private void listBox1_DrawItem(object sender, DrawItemEventArgs e) {
    AppearanceObject appearance = appearanceCollection[e.Index];
    using (SolidBrush brush = new SolidBrush(appearance.BackColor)) {
        e.Graphics.FillRectangle(brush, e.Bounds);
    }
    using (SolidBrush fbrush = new SolidBrush(appearance.ForeColor)) {
        e.Graphics.DrawString("Style Sample", appearance.Font, fbrush, e.Bounds);
    }
}

Now you need to customize the list box to make it the source for drag and drop operations. This will be performed in the MouseDown event handler. It will check whether the mouse cursor is currently over an item and if so, dragging will be initialized using the DoDragDrop method call. The item’s caption (that is the same as the corresponding style name) will then be passed to this method as the data to be dragged. See the code below.

private void listBox1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) {
   ListBox lb = sender as ListBox;
   int itemIndex = lb.IndexFromPoint(e.X, e.Y);
   if (itemIndex != -1) {
      string dragData = lb.Items[itemIndex].ToString();
      lb.DoDragDrop(dragData, DragDropEffects.Copy);
   }
}

One more thing to be done is to handle the dragging process. This implies handling the DragOver event of the vertical grid control. The handler will determine whether a row header or a cell is located underneath the mouse pointer and if so, it will allow dropping. Note that you must use the VGridControlBase.CalcHitInfo method to determine which element is at the specified point. Please refer to the Obtain Hit Information topic for details on using this method.

The code below demonstrates how the dragging process is handled.

private void vGridControl1_DragOver(object sender, System.Windows.Forms.DragEventArgs e) {
   VGridControl grid = sender as VGridControl;
   Point testPoint = grid.PointToClient(new Point(e.X, e.Y));
   VGridHitInfo hitInfo = grid.CalcHitInfo(testPoint);
   if (hitInfo.Row != null)
      e.Effect = DragDropEffects.Copy;
   else
      e.Effect = DragDropEffects.None;
}

The last thing to complete the sample is to handle dropping. This involves writing a handler for the DragDrop event of the vertical grid. The handler determines the row located underneath the mouse pointer and assigns the dragged style to it. The BaseRow.StyleName property is used to specify row style. See the code below.

private void vGridControl1_DragDrop(object sender, System.Windows.Forms.DragEventArgs e) {
   VGridControl grid = sender as VGridControl;
   // Obtaining the hit information.
   Point testPoint = grid.PointToClient(new Point(e.X, e.Y));
   VGridHitInfo hitInfo = grid.CalcHitInfo(testPoint);
   // Obtaining the dragged data - the appearance name.
   string styleName = e.Data.GetData(DataFormats.Text).ToString();
   // Applying the appearance settings to the row.
   AppearanceObject appearance = GetAppearanceByName(appearanceCollection, styleName);
   if(appearance != null)
      hitInfo.Row.Appearance.Combine(appearance);
}

Complete Code

using DevExpress.Utils;
using DevExpress.XtraVerticalGrid;

AppearanceObject[] appearanceCollection;
private void Form1_Load(object sender, System.EventArgs e) {
   // ...
   AppearanceObject appearanceBlue = new DevExpress.Utils.AppearanceObject("Blue appearance");
   appearanceBlue.BackColor = Color.LightGray;
   appearanceBlue.ForeColor = Color.Black;
   appearanceBlue.Font = new Font(appearanceBlue.Font, FontStyle.Italic);
   AppearanceObject appearanceGreen = new DevExpress.Utils.AppearanceObject("Green appearance");
   appearanceGreen.BackColor = Color.Yellow;
   appearanceGreen.ForeColor = Color.Black;
   appearanceGreen.Font = new Font("Tahoma", 10, FontStyle.Bold);

   appearanceCollection = new DevExpress.Utils.AppearanceObject[]{appearanceBlue, appearanceGreen};

   // Initializing the list box.
   listBox1.Items.Add("Blue appearance");
   listBox1.Items.Add("Green appearance");
   listBox1.DrawMode = DrawMode.OwnerDrawVariable;
   // Enabling dropping onto the vertical grid.
   vGridControl1.AllowDrop = true;
}

private void listBox1_MeasureItem(object sender, System.Windows.Forms.MeasureItemEventArgs e) {
   AppearanceObject appearance = appearanceCollection[e.Index];
   e.ItemHeight = (int) e.Graphics.MeasureString("Style Sample", appearance.Font).Height;
}

private void listBox1_DrawItem(object sender, DrawItemEventArgs e) {
    AppearanceObject appearance = appearanceCollection[e.Index];
    using (SolidBrush brush = new SolidBrush(appearance.BackColor)) {
        e.Graphics.FillRectangle(brush, e.Bounds);
    }
    using (SolidBrush fbrush = new SolidBrush(appearance.ForeColor)) {
        e.Graphics.DrawString("Style Sample", appearance.Font, fbrush, e.Bounds);
    }
}

private AppearanceObject GetAppearanceByName(DevExpress.Utils.AppearanceObject[] collection, string appearanceName) {
   for(int i = 0; i < collection.Length; i++) {
      if(collection[i].Name == appearanceName)
         return collection[i];
   }
   return null;
}

private void listBox1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) {
   ListBox lb = sender as ListBox;
   int itemIndex = lb.IndexFromPoint(e.X, e.Y);
   if (itemIndex != -1) {
      string dragData = lb.Items[itemIndex].ToString();
      lb.DoDragDrop(dragData, DragDropEffects.Copy);
   }
}

private void vGridControl2_DragOver(object sender, System.Windows.Forms.DragEventArgs e) {
   VGridControl grid = sender as VGridControl;
   Point testPoint = grid.PointToClient(new Point(e.X, e.Y));
   VGridHitInfo hitInfo = grid.CalcHitInfo(testPoint);
   if (hitInfo.Row != null)
      e.Effect = DragDropEffects.Copy;
   else
      e.Effect = DragDropEffects.None;
}

private void vGridControl2_DragDrop(object sender, System.Windows.Forms.DragEventArgs e) {
   VGridControl grid = sender as VGridControl;
   // Obtaining the hit information.
   Point testPoint = grid.PointToClient(new Point(e.X, e.Y));
   VGridHitInfo hitInfo = grid.CalcHitInfo(testPoint);
   // Obtaining the dragged data - the appearance name.
   string styleName = e.Data.GetData(DataFormats.Text).ToString();
   // Applying the appearance settings to the row.
   AppearanceObject appearance = GetAppearanceByName(appearanceCollection, styleName);
   if(appearance != null)
      hitInfo.Row.Appearance.Combine(appearance);
}

The image below shows the appearance of the list box and the vertical grid control as well as illustrating how dragging can be performed between them.

DragDrop - Target