Drag and Drop en WinForms

viernes, 5 de septiembre de 2008

Hace unos días durante un curso de capacitación un cliente nos comentó que necesitaban implementar una grilla cuyas filas fueran reordenables mediante "drag and drop" (es decir arrastrando y soltando) y vergonzosamente tuvimos que reconocer que apenas teníamos una (muy vaga) idea teórica de como implementarlo.

A la semana siguiente con la intención de dar un respuesta un poco más sólida, dediqué unos minutos a leer un poco y dado que resultaba fácil, armé una pequeña demo para probar el uso de Drag and Drop en WinForms.

Demo

El código puede descargarse de aquí.

En el ejemplo hay un simple DataGridView al cual se puede arrastrar un archivo Xml, cuyo formato sea "convertible" a DataSet, con lo cual la tabla (la primera si hay más de una) se muestra en la grilla (en el ejemplo incluí un Items.xml que sirve a tal fin).

Una vez que tengo filas en la grilla, puedo arrastrar filas con el mouse para modificando el orden.

Esto muestra como realizar Drag n Drop, desde una aplicación externa (Explorador de Windows por ejemplo) hacia un control WinForms propio, y como hacerlo desde y hacia la misma aplicación.

Paso a Paso
  • Lo primero que necesitamos es iniciar el "arrastre", y una forma posible es en el evento MouseMove del control de origen, para esto agregue en el código de este evento una llamada al método "DoDragDrop" (cuando el botón izquierdo está presionado, etc.), al cual se le debe pasar como argumentos el objeto a arrastrar (en mi caso el DataGridViewRow que se esta arrastrando), que simplemente sirve como información para el control de destino, y la acción deseada, por ej. "Move".
  • Con esto ya podemos tomar una fila y llevarla por toda la pantalla, sin embargo todavía nadie acepta nuestro "DataGridViewRow", con la cual el cursor muestra el conocido símbolo de prohibido.
  • Lo que necesitamos ahora es que nuestra grilla diga "Vienes con un DataGridViewRow? Puedes soltarlo aquí!", lo que hace que el cursor se transforme en uno más amigable indicando la acción permitida.
  • Para esto hay que agregar código en el evento "DragOver", en este una vez que me aseguro que el objeto arrastrado es una DataGridViewRow, perteneciente a mi misma grilla, informo mediante un argumento del evento "DragOver" que la acción permitida es (como fue solicitado) "Move".
  • Finalmente tengo que hacerlo cuando el objeto es soltado, esto ocurre en el evento "DragDrop", en el cual verifico nuevamente que estoy recibiendo una DataGridViewRow de mi propia grilla, y realizo finalmente el movimiento de filas (lo cual dependerá de la fuente de datos de la grilla (DataTable, DataView, List, etc.).

De forma similar en DragOver y DragDrop espero un objeto con formato "FileName" (el cual nos envía el Windows Explorer) para aceptar archivos .xml sobre la grilla. Lo cual muestra que el origen y destino pueden estar en aplicaciones separadas, y tecnologías diferentes, ya que Drag and Drop es una funcionalidad propia del Sistema Operativo.

Esto por supuesto no abarca todas las posibilidades como por ejemplo mostrar un icono personalizado durante el arrastre, arrastrar información en diferentes formatos, etc. Pero es un buen ejemplito introductorio.