Sobre controles creados de forma dinamica

Iniciado por rulovive, 25 Abril 2018, 00:28 AM

0 Miembros y 1 Visitante están viendo este tema.

rulovive

Buenas gente. tengo una form donde me da la necesidad de crear controles de forma dinamica (especificamente son picture boxes que contienen datos para acomodarlos en ciertos espacios en mi form), pero son varias veces las que creo un control y lo manipulo y lo muevo. el problema es que cuando tengo uno creado y creo otro nuevo, los eventos creados de forma dinamica para el control solo se aplican al mas reciente creado, y el anterior pierde la capacidad de manejarse con los eventos creados dinamicamente... ejemplo:

crear picturebox nuevo;
crear evento dinamico mouse up; <-- Evento que me da problema


Se supone que este evento consiste simplemente en que cuando suelto el raton despues de arrastrarel objeto, me lo acomoda en cierta area del form automaticamente, y lo hace tantas veces como yo quiera... pero si lo acomodo y creo otro control igual, el evento pasa a funcionar solamente para el cntrol mas reciente que se creó, y si arrastro y suelto el boton del control creado en primer lugar, ya no funciona el evento... y creo que es porque de cierta manera "caducó", ya que existe un control creado de manera mas reciente.... como puedo arreglar esto?

El Benjo

Hola, creo que tu problema es precisamente por lo que comentas. Lo que puedes intentar es crear una lista de PictureBox y agregar cada PictureBox que creas. Ejemplo:

Código (csharp) [Seleccionar]

public partial class MainForm : Form
{
// Lista de picture box.
List<PictureBox> listaPictureBox = new List<PictureBox>();

public MainForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();

//
// TODO: Add constructor code after the InitializeComponent() call.
//
}

void MainFormLoad(object sender, EventArgs e)
{
PictureBox newPicture = new PictureBox();
// Agregar controlador de evento.
listaPictureBox.Add(newPicture); // Agrego el picturebox a la lista.
}
}


Pero debes recordar eliminar cada PictureBox que ya no necesites, para no saturar la memoria. También, deberías mostrar la manera en que creas la instancia de los PictureBox y cómo agregas el manejador del evento.
www.es.neftis-ai.com

Sí hay un mejor lenguaje de programación y es ese con el que puedes desarrollar tus objetivos.

Eleкtro

Un controlador de evento no "caduca" hasta que la clase/control se libera o te desuscribes arbitrariamente a dicho evento usando el operador de resta y asignación ( -= ).

Muestra el código donde creas los controles en tiempo de ejecución y te suscribes a X evento, ya que algo debes estar haciendo incorrectamene.

Saludos!








rulovive

#3
a ver pongo el codigo... la cosa es asi. estoy haciendo un libro de citas, entonces cada picturebox es una "etiqueta", que indica qe un espacio esta reservado para cita, entonces van a estar varios boxes en el libro, y solo cuando cancelen una cita se elimina el picture box que le corresponde, entonces el propietaro deberia recorrer los demas horarios para eliminar el tiempo muerto, pero el evento mouse_up (que funciona haciendo que cuando el raton suelte el objeto, se acomode de manera automatica en el lugar correspondiente a cierto horario -es decir, que la etiqueta se acomode a las 5:30, y no a las 5:12:24) ya no funciona, y hace que el usuario tenga que estar contando las marquitas de los minutos hasta que le atine a las 5:30... pongo el codigo completo:

Código (csharp) [Seleccionar]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace airline
{
    public partial class Form1 : Form
    { public PictureBox jalador;
        public string hora, notas;
        public bool cita = false;

       
        public Form1()
        {
            InitializeComponent();
        }

        private void pictureBox2_Click(object sender, EventArgs e)
        {
            Form Form2 = new Form2();
            Form2.Owner = this;
            Form2.ShowDialog(this);
           


           
           
        }

        private void Jalador_MouseEnter(object sender, EventArgs e)
        {
            jalador.Cursor = Cursors.Hand;     
        }

        private void pictureBox2_MouseEnter(object sender, EventArgs e)
        {
            pictureBox2.Height = 32;
            pictureBox2.Width = 74;
        }

        private void pictureBox2_MouseLeave(object sender, EventArgs e)
        {
            pictureBox2.Height = 30;
            pictureBox2.Width = 72;
        }

        private void pictureBox3_MouseEnter(object sender, EventArgs e)
        {
            pictureBox3.Height = 32;
            pictureBox3.Width = 73;
        }

        private void pictureBox3_MouseLeave(object sender, EventArgs e)
        {
            pictureBox3.Height = 30;
            pictureBox3.Width = 71;
        }

        private void pictureBox3_Click(object sender, EventArgs e)
        {

           
        }

        private void Boton_Click(object sender, EventArgs e)
        {
            MessageBox.Show("hola");
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (cita == true)
            { jalador = new PictureBox();
                    jalador.Location = new System.Drawing.Point(450, 450);
                    //de 25 en 25 cada media hora, y el 38 es siempre igual
                    jalador.SizeMode = PictureBoxSizeMode.AutoSize;

                if (hora == "0:30")
                    jalador.Image = Image.FromFile(@"C:\Users\Constructora\Desktop\res\jalador.png");
                if (hora == "1:00")
                    jalador.Image = Image.FromFile(@"C:\Users\Constructora\Desktop\res\jaladoruna.png");
                if (hora == "1:30")
                    jalador.Image = Image.FromFile(@"C:\Users\Constructora\Desktop\res\jaladorunaymedia.png");
                if (hora == "2:00")
                    jalador.Image = Image.FromFile(@"C:\Users\Constructora\Desktop\res\jaladordos.png");             
                if (hora == "2:30")
                    jalador.Image = Image.FromFile(@"C:\Users\Constructora\Desktop\res\jaladordosymedia.png");
                if (hora == "3:00")
                    jalador.Image = Image.FromFile(@"C:\Users\Constructora\Desktop\res\jaladortres.png");
                if (hora == "3:30")
                    jalador.Image = Image.FromFile(@"C:\Users\Constructora\Desktop\res\jaladortresymedia.png");           
                if (hora == "4:00")
                    jalador.Image = Image.FromFile(@"C:\Users\Constructora\Desktop\res\jaladorcuatro.png");             
                if (hora == "4:30")
                    jalador.Image = Image.FromFile(@"C:\Users\Constructora\Desktop\res\jaladorcuatroymedia.png");             
                if (hora == "5:00")
                    jalador.Image = Image.FromFile(@"C:\Users\Constructora\Desktop\res\jaladorcinco.png");             
                if (hora == "5:30")
                    jalador.Image = Image.FromFile(@"C:\Users\Constructora\Desktop\res\jaladorcincoymedia.png");
                if (hora == "6:00")
                   jalador.Image = Image.FromFile(@"C:\Users\Constructora\Desktop\res\jaladorseis.png");
                 
                Controls.Add(jalador);
                jalador.Visible = true;
                jalador.BringToFront();
                ControlExtension.Draggable(jalador, true);
                jalador.LocationChanged += Jalador_LocationChanged1;
                jalador.MouseUp += Jalador_MouseUp;
                jalador.MouseEnter += Jalador_MouseEnter1;
                cita = false;
            }
        }

        private void Jalador_MouseEnter1(object sender, EventArgs e)
        {
            // Create the ToolTip and associate with the Form container.
            ToolTip toolTip1 = new ToolTip();

            // Set up the delays for the ToolTip.
            toolTip1.AutoPopDelay = 5000;
            toolTip1.InitialDelay = 500;
            toolTip1.ReshowDelay = 500;
            // Force the ToolTip text to be displayed whether or not the form is active.
            toolTip1.ShowAlways = true;

            // Set up the ToolTip text for the Button and Checkbox.
            toolTip1.SetToolTip(this.jalador ,"~~Datos de la cita~~\n Duración estimada del servicio: "+ hora+"\n Detalles: "+notas);
           
        }

        private void Jalador_MouseUp(object sender, MouseEventArgs e)
        {
            if (jalador.Location.X <= 171)
                jalador.Left = 145;
            if (jalador.Location.X > 171 && jalador.Location.X <= 225)
                jalador.Left = 200;
            if (jalador.Location.X > 225 && jalador.Location.X <= 280)
                jalador.Left = 255;
            if (jalador.Location.X > 280 && jalador.Location.X <= 335)
                jalador.Left = 310;
            if (jalador.Location.X > 335 && jalador.Location.X <= 390)
                jalador.Left = 365;
            if (jalador.Location.X > 390 && jalador.Location.X <= 445)
                jalador.Left = 420;
            if (jalador.Location.X > 445 && jalador.Location.X <= 500)
                jalador.Left = 475;
            if (jalador.Location.X > 500 && jalador.Location.X <= 555)
                jalador.Left = 530;
            if (jalador.Location.X > 555 && jalador.Location.X <= 610)
                jalador.Left = 585;
            if (jalador.Location.X > 610 && jalador.Location.X <= 665)
                jalador.Left = 640;
            if (jalador.Location.X > 665 && jalador.Location.X <= 720)
                jalador.Left = 695;
            if (jalador.Location.X > 720)
                jalador.Left = 750;

            if (jalador.Location.Y <= 180)
                jalador.Top = 166;
            if (jalador.Location.Y > 180 && jalador.Location.Y <= 225)
                jalador.Top = 204;
            if (jalador.Location.Y > 225 && jalador.Location.Y <= 260)
                jalador.Top = 242;
            if (jalador.Location.Y > 260 && jalador.Location.Y <= 300)
                jalador.Top = 280;
            if (jalador.Location.Y > 300 && jalador.Location.Y <= 340)
                jalador.Top = 318;
            if (jalador.Location.Y > 340 && jalador.Location.Y <=375 )
                jalador.Top = 356;
            if (jalador.Location.Y > 375)
                jalador.Top = 394;



        }

        private void Jalador_LocationChanged1(object sender, EventArgs e)
        {
            label2.Text = (jalador.Location.X + "," + jalador.Location.Y);
           
        }

   

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            label1.Text = (Cursor.Position.X + "," + Cursor.Position.Y);
        }

     

    }
}



entonces ahi el problema es que si yo tengo 5 citas, y me cancelan la segunda, elimino ese picturebox que corresponde a la segunda cita, pero el evento que inicia en la linea 138 ya no sirve, salvo para el picture box mas reciente...

Serapis

#4
¿Puedes poner una captura de la ventana?.

Lo explicas un poco engorroso, y resulta difícil seguir que quieres exactamente.
Por alguna de tus explicaciones más clara, concluyo que tienes citas a x horas relacionadas con cada cita, la cita se anula, y tu qieres que el contenido desaparezca y quede libre el tiempo que ocupaba dicha cita.

Bien... la idea de que uses un picturebox por cada cita, resulta exagerado... e innecesario y al final no es acorde. Cuando de un tipo de datos existen muchos, es cuando surgen los arrays, diccionarios, colecciones en general, y no andar con ítems sueltos a mansalva, dífíciles de controlar, de ubicar... las colecciones tieen precisamente métodos para tener controlado todo eso.

----------------------------------------------
- Para mostrar las citas y que el usuario haga click, mouse up, mouse enter, etc... para un proyecto así, lo razonable es tener:
- Una colección que aloje ítems de cita. Preferiblemente que estén ordenados por fecha y hora.
- Un ítem de cita puede ser una estructura, si ha de contener datos simples o una clase si ha de contener datos más complejos.
- Luego en la parte de la interfaz, cualquier tipo de lista de una o más columnas. Que muestren al menos uno o dos campos de la estructura/clase. Razón de la cita y hora, será lo habitual si es de una sola columna, incluso el nombre del citado si tienes más columnas.
- Y unos botones para manipular la lista, al menos estos: Añadir cita, eliminar cita, modificar cita, ver detalles de cita (aunque los detalles podrían ser doble click sobre el ítem en la lista).. Con cada boton se abre una ventana en unos casos para rellenar o para leer, o bien solicitar confirmación (caso de eliminar).
El botón detalles, mostrará otros campos que no aparecen en la lista...
De modo alternativo a los botones, puede ser un menú, o mejor aún un popup-menú sobre la propia lista.
-----------------------------------------------

Aparte puedes poner algún tipo de avisador de la cita que llega a su hora, incluso un checkbox, de 'avísame 5 minutos antes de la cita', en tal caso con un aviso luminoso (por ejemplo cambiando el color del fondo del ítem o del texto alternando entre dos colores).
Y finalmente el timer que escruta las citas. Las colección debería ser ordenada por la fecha-hora de la cita. Así el timer, solo tiene que chequear la primera cita de la lista.

Cuando la cita de la lista vence, mejor que eliminarla del todo, pasarla a otra lista oculta, en orden inverso... y rellenar un campo de tipo: "resultado de la cita", con una valor enumerado: anulado, retrasado a otro día, atendido, etc... mantenerlas quizás un día, una semana antes de eliminarlas definitivamente (mejor que decida el usuario el tiempo que deba pasar antes de eliminarla del todo). Por supuesto un botón de consultar citas pasadas, será necesario, si no no tendría sentido ese otro listado oculto... No porque una cita haya pasado, deja de ser útil sus datos.

Solo con lo comentado entras las dos líneas de rayas, te basta y sobra y será más elegante e intuitivo que lo que me parece entender que estás haciendo, además es sencillo de implementar.

rulovive



imagenes de izquierda a derecha... a ver si con esto se entiende mejor