domingo, 9 de mayo de 2010

Guía simple: Drag-and-Drop en Windows Forms

crab-icon ball c#

Hoy en The Code Crab vamos a empezar a picar un poco de código, que siendo un blog de programación como que ya va tocando. Vamos a implementar Drag-and-Drop paso a paso, de forma sencilla con un pequeño ejemplo que os podréis descargar, pero no será nada difícil añadirlo a vuestro programas grandes.

Drag-and-Drop es una propiedad que tienen algunas interfaces graficas que permite mover objetos de un lugar a otro tan solo arrastrándolos con el ratón.

En mi caso utilizare visual studio 2010, pero esto funciona en cualquier versión de VS sin ningún problema (os dará problemas los archivos de solución quizás, pero el código en principio no). Con esto abrimos el VS, creamos un nuevo proyecto (Aplicación de windows forms en c#) y creamos una interfaz grafica simple para el ejemplo, que constara de dos listBox, aunque con un par de transformaciones el código debería funcionar sin muchos problemas para otros contenedores similares.

elefantes1Es importante que busquéis en las propiedades de los listBox la propiedad enableDrop y que la pongáis a True, sin esto el programa no funcionara. Después de esto nos metemos a modificar el código (Ver->Código)

Aquí tendremos que crear varios métodos para hacer funcionar el Drag-and-Drop. Necesitaremos dos métodos para poder coger objetos de un listBox y otros dos para poder soltar objetos en un listBox. Como queremos que se pueda cojer objetos de ambos vamos a implementar los 4 métodos una vez para cada listBox. No los repetiré por aquí pero si tenéis alguna duda podéis consultar el código que hay al final.

El primer método se llama Mouse Down, y es el evento que se dispara al pulsar sobre un elemento del listBox. Hace falta para poder sacar objetos de un componente.



///
/// Evento disparado cuando se pincha sobre un objeto de un listBox, se empieza el drag and drop
///

private void listBox1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
int indexOfItem = listBox1.IndexFromPoint(e.X, e.Y);
//se almacena la posición donde esta colocado el objeto que vamos a mover
if (indexOfItem >= 0 && indexOfItem < listBox1.Items.Count)
{
//Escojemos que tipo de Drag and Drop queremos. Mi consejo es usar Copia aunque quieras mover, y quitar los objetos
//manualmente una vez que se pose el objeto, así evitaremos que si el usuario suelta el objeto fuera de un listBox,
//este se pierda.
listBox1.DoDragDrop(listBox1.Items[indexOfItem], DragDropEffects.Copy);
}
}


El siguiente método se dispara cuando se suelta un objeto en el mismo componente que se cogió, provocando así una reorganización. Se llama DragOver


 
///
/// Evento disparado al soltar un objeto en el mismo sitio donde se ha cojido
///

private void listBox1_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
{

indice =
listBox1.IndexFromPoint(listBox1.PointToClient(new Point(e.X, e.Y)));
//Cambiamos el objeto seleccionado de posición, en funcion de donde se suelte
listBox1.SelectedIndex = indice;
}


Con esto concluyen los eventos para cojer objetos de un listBox. Ahora vamos con los necesarios para soltar un objeto en un componente, empezamos con DragDrop, evento que se dispara al soltar un objeto en un listBox



///
/// Evento disparado al soltar un objeto en un listBox distinto al que se cojio
///

private void listBox1_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
//Podemos cambiar el formato en funcion del objeto que tengamos en listBox.Items, pero hay que tener cuidado
//por que aunque items acepte cualquier objeto, no hay formatos de Drag and Drop para todo.
listBox1.Items.Remove(e.Data.GetData(DataFormats.Text));
if (indice >= 0 && indice < listBox1.Items.Count)
{
//Si se solto en la parte alta se pone el objeto donde corresponde
listBox1.Items.Insert(indice, e.Data.GetData(DataFormats.Text));
}
else
{
//Sino se pone en el fondo
listBox1.Items.Add(e.Data.GetData(DataFormats.Text));
}
//quitamos el objeto en el listBox2, para conseguir manualmente el efecto mover (explicado anteriormente)
listBox2.Items.Remove(e.Data.GetData(DataFormats.Text));
}


Y por ultimo hacemos un método mas, DragEnter, disparando cuando se entra con el ratón a un listBox arrastrando un objeto




/// Evento disparado al arrastrar un objeto dentro del listBox
///
public void listBox1_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
{

// Cambiamos el cursor del raton para indicar que el objeto arrastrado se puede soltar aquí
e.Effect = DragDropEffects.Copy;

}


Para que nuestro programa funcione bien debemos tener estos métodos 2 veces, uno para listBox1 y otro para listBox2, con cuidado de cambiar las referencias a estos. Tras esto solo nos queda añadir los eventos a las listBox, que lo haremos en el constructor de la clase, después de la llamada al método InitializeComponent();



//No hay que olvidarse de agregar todos los metodos que hicimos o no servira de nada
listBox1.MouseDown += new System.Windows.Forms.MouseEventHandler(listBox1_MouseDown);
listBox1.DragOver += new System.Windows.Forms.DragEventHandler(listBox1_DragOver);
listBox1.DragDrop += new System.Windows.Forms.DragEventHandler(listBox1_DragDrop);
listBox1.DragEnter += new System.Windows.Forms.DragEventHandler(listBox1_DragEnter);

listBox2.MouseDown += new System.Windows.Forms.MouseEventHandler(listBox2_MouseDown);
listBox2.DragOver += new System.Windows.Forms.DragEventHandler(listBox2_DragOver);
listBox2.DragDrop += new System.Windows.Forms.DragEventHandler(listBox2_DragDrop);
listBox2.DragEnter += new System.Windows.Forms.DragEventHandler(listBox2_DragEnter);


Y voila, tras todo esto ya tenemos nuestro programa funcionando con Drag-and-Drop. ¿No ha sido tan difícil, no?



elefantes2Podéis descargar aquí el código fuente en caso de que os halla quedado alguna duda: http://www.megaupload.com/?d=GM4O9V65



Pues eso es todo por hoy, muchas gracias por leerme y ¡Sed buenos cangrejos!565

1 comentario: