1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

Aplicação em C# com event handling

Discussão em 'Programação' iniciada por candycane, 18 de Maio de 2008. (Respostas: 22; Visualizações: 3089)

  1. candycane

    candycane Power Member

    Boa noite comunidade! :)

    Preciso desenvolver uma aplicação em que crie x números de botões consoantes o numero de registo que tenha na base de dados. Ate aqui tudo bem, mas a minha duvida é:

    como eu faço para que ao clicar no botão x vá ter as propriedades desse registo em questão? :(

    A aplicação é para um café, em que pretendo ter um botão para cada mesa da sala, e ao clicar no botão da mesa x me diga os pedidos que fizeram dessa mesa.


    Acho que será necessário event handling, não?

    Qualquer ajuda é muito bem vinda :)
     
  2. balute

    balute Power Member

    Para adicionar um event handler para cada botão, basta fazer isto:
    Código:
    botao[x].Click += new System.EventHandler(this.CliqueDeBotao);
    Isto faz com que a subrotina CliqueDeBotao seja o event handler do evento Click do botão botao[x]. Claro que a sub tem que ter a mesma assinatura (mesmos parâmetros) que o delegate do evento correspondente.
     
  3. andrepadez

    andrepadez Power Member

    Boas. Eu deparei-me com esse problema há uns dias, e consegui resolvê-lo com algum esforço.

    1º - tens de decidir o que te dá mais jeito - ter um eventhandler para cada botão, o que pode tornar o código demasiado extenso e redundante ou ter um eventhandler que dependendo do botão clickado, receba esses parâmetros e chame os métodos correspondentes.
    Se a tua opção for a 1ª, podes fazer exactamente como o Wizzard-of-War disse e não terás problemas.
    Se escolheres a segunda, também não tem muito que saber, embora tenhas de abandonar um pouco a ajuda do "Visual". O que eu fiz foi criar um array de botões, cada um com uma propriedade que o torna único (no meu caso um simples X,Y), e no eventhandler, como recebes como argumento o próprio objecto que o chamou, extrais essas propriedades únicas e chamas os métodos em função do botão que o chamou.

    Se decidires usar esta segunda opção, diz qq coisa, que eu passo-te o código do que fiz.
     
  4. candycane

    candycane Power Member

    Obrigada pelas ajudas :)

    andrepadez prefiro o 2º metodo, era algo assim que tinha em mente. Só que nunca usei event handling :(
     
  5. andrepadez

    andrepadez Power Member

    Este problema então vai um pouco além do EventHandler. Provalvelmente alguem mais entendido em programação vai dizer que há forma melhor de fazer isto. Eu agradeço, mas esta foi a forma como consegui resolver o que precisava.

    Comecemos pelo início:
    1º - Convem perceberes que código o Visual C# gera ao colocar um botão (ou o objecto da Toolbox que quiseres usar, vamos supor que é um botão)
    a) Coloca um botão na tua form de forma normal e faz duplo click nele para o programa criar o EventHandler tb,
    b) Vais ver o código do formdesigner que foi gerado pelo botão. Gera logo uma série de linhas para declarar o botão, declarar o nome, definir o tamanho, a posição, etc.
    podes até copiar este código para um ficheiro de texto, para depois ir buscá-lo mais facilmente. Podes apagar o botão que criaste.
    Código:
     
                this.button1 = new System.Windows.Forms.Button();
                this.SuspendLayout();
                // 
                // button1
                // 
                this.button1.Location = new System.Drawing.Point(12, 12);
                this.button1.Name = "button1";
                this.button1.Size = new System.Drawing.Size(75, 23);
                this.button1.TabIndex = 0;
                this.button1.Text = "button1";
                this.button1.UseVisualStyleBackColor = true;
                this.button1.Click += new System.EventHandler(this.button1_Click);
    
    2º - Pô-los no form
    a)no form principal, declaras um array (ou matriz) de botões (como global)
    Código:
    Button[] botoes = new button[nºde botões]
    no método Form_Load(), constróis o array no ecrã com um for (recorrendo ao código que guardaste, só tens de alterar umas ceninhas, como retirar o this):
    Código:
     
    for (i = 0; i < nºbotões; i++)
    {
        botoes[i] = new Button();
        botoes[i].Name = "botao" + i;
        botoes[i].Size = new System.Drawing.Size(75,23);
        ....
        botoes[i].Click += new System.EventHandler(Botoes_Click);
    }
    
    Notas: quanto ao nome, o iterador i é uma maneira de dares uma propriedade única ao botão, de forma a poderes distinguí-lo dos outros quando for clickado; a localização de cada um, pode ser definido dentro do for se a distância entre eles for sempre regular, senão defines uma a uma com botoes[0].Location = new System.Drawing.Point(12,12); botoes[1].Location = ...; Desta maneira, com o EventHandler a ser sempre o mesmo, ele vai receber como argumento o botão que foi clickado.

    No código do form, vais então criar o método Eventhandler com o nome que puseste entre-parenteses, e da seguinte forma:

    Código:
    private Void Botoes_Click (object sender, EventArgs e)
    Lá dentro vais ter de declarar uma variável que receba as propriedades do botão que invocou a função:
    Código:
     
    Button variavel = (Button) sender;
    
    a partir daqui podes fazer o que quiseres como:
    Código:
     
    if variavel.Name = "botao0"
         método0();
    else if variavel.Name = "botao1"
        método1();
    
    assim, quando o user clicka num, botão sabes que está a chamar o método correspondente.


    Espero que te tenha clarificado, foi um pouco difícil de transcrever isto para o que querias que as minhas necessidades eram um pouco diferentes ( um tabuleiro de xadrez com uma classe que herda de PictureBoxes), mas a filosofia é a mesma. Qualquer coisa apita, se quiseres tb te mando o código do que fiz, para veres melhor como posicionei as cenas no ecrã, etc.
    Não te esqueças que tb podes criar uma classe que herde de Button e acrescentes as propriedades e os métodos que quiseres.

    Fica bem
     
  6. balute

    balute Power Member

    Na verdade, não é necessário complicar muito. Para obter o índice do botão clicado no array de botões, dentro da subrotina que faz handling do evento, pode-se fazer assim:
    Código:
    Button botaoClicado = (Button)sender;
    int indiceDoBotao = Array.IndexOf(Botao, botaoClicado, 0);
     
  7. andrepadez

    andrepadez Power Member

    Tens razão, não tinha pensado nisso; como tinha propriedades x,y usei-as e aqui foi a maneira que me lembrei. Thx wizzard
     
  8. candycane

    candycane Power Member

    Muito obrigada a todos! :)

    Acho que já vou conseguir resolver o problema :D
     
  9. candycane

    candycane Power Member

    Há alguma maneira de eu guardar numa variável dentro do meu EventHandler o texto que dei ao botão?

    O nome que dei aos botões foi o nome das mesas que estao na base de dados.

    Se conseguisse ter apenas o nome já conseguia fazer um query em que o meu where seria o nome da mesa do botao clicado.

    O que me aparece é: System.Windows.Forms.Button, Text: mesa: M01

    O que queria é apenas o M01, tentei com substring mas sem sucesso :(

    a parte do botao esta assim:

    for (int i = 0; i < (count / 3); i++)
    {
    for (int j = 0; j < (count / 7); j++)
    {
    sr.Read();
    btn_mesa[i, j] = new Button();
    btn_mesa[i, j].Name = "botao" + i;
    btn_mesa[i, j].Location = new Point(120 * i, 100 * j);
    btn_mesa[i, j].Size = new Size(100, 80);
    btn_mesa[i, j].Text = "Mesa: \n " + sr["id_mesa"].ToString();
    pnl_inicio.Controls.Add(btn_mesa[i, j]);
    btn_mesa[i, j].Click += new System.EventHandler(this.btn_click);
    }
    }

    o meu sr é o meu SqlDataReader.
     
    Última edição: 20 de Maio de 2008
  10. balute

    balute Power Member

    Para obter todas as propriedades do botão no event handler:
    Código:
    Button botaoClicado = (Button)sender;
    //botaoClicado.Text - devolve o texto do botão
    //botaoClicado.Name - devolve o nome do botão
    //...
     
  11. candycane

    candycane Power Member

    Muito obrigada!!!

    Ja vou poder avançar e muito na aplicação :)
     
  12. candycane

    candycane Power Member

    Acho que vou precisar que vocês me deem uma luz novamente. :\

    eu fiz a aplicação com panels, e coloquei um botao para voltar a tras(para a ver todas a mesas)

    so que n me limpa os dados do botão anterior. Então pnsei que tinha que fazer o metodo ao contrario, remover os Controls.

    Fiz da seguinte maneira, mas não me esta a limpar as labels :(


    public void remover_control()
    {
    List<Control> controlsRemover = new List<Control> ();
    foreach (Control c in this.Controls)
    {
    if (c is Label)
    {
    controlsRemover.Add(c);
    }
    }
    foreach (Control remove in controlsRemover)
    {
    this.Controls.Remove(remove);
    remove.Dispose();
    }


    dentro do meu botao voltar a tras chamo essa funçao, mas não me entra no if (c is Label)
     
  13. JumpeR

    JumpeR Power Member

    Acho que estao a complicar, n sei que eventos keres....

    mas no msm sitio das properties tens la a lista com os eventos para esse control, dps double click e ele cria logo...

    Repito, n sei se keres fazer algo muito especifico...mas os basicos tao la...tipo mouse over, etc
     
  14. balute

    balute Power Member

    Não percebi porque é que decidiste remover os controls, mas para remover todos os controls faz-se assim:
    Código:
            private List<Control> obterControls(Control parent)
            {
                List<Control> l = new List<Control>();
                foreach (Control c in parent.Controls)
                {
                    l.Add(c);
                    l.AddRange(obterControls(c));
                }
                return l;
            }
    
            public void remover_controls(Control parent)
            {
                foreach (Control c in obterControls(parent))
                    c.Parent.Controls.Remove(c);
            }
    Se quiseres apenas remover alguns controls (por exemplo, todas as labels), basta pôr uma condição antes da linha l.Add(c):
    Código:
    if (c is Label)
        l.Add(c);
    Estamos a falar de event handling para controls criados durante a execução do programa, não durante o design. ;)
     
    Última edição: 21 de Maio de 2008
  15. candycane

    candycane Power Member

    decidi remover pk quando volto a tras, a lista das mesas, ao clicar noutro botao de outra mesa, os dados da mesa anterior n apagam :(
    Ficam uns em cima dos outros :\

    Tou a buscar os dados a partir da BD.

    Por ex, clico na mesa M01 e vejo os pedidos dessa mesa, quanco clico em voltra atras, vou ter novamente os botoes de todas a mesas. Clico no botao da mesa M02 e os pedidos da mesa M01 continuam lá, e os da M02 ficam por cima :(

    Tou a fazer com panels, um panel pros botoes das mesas todas, e outro panel com os detalhes de cada mesa. Será por isso?
     
  16. balute

    balute Power Member

    Mas, ao clicares numa mesa, os dados dos controls que mostram os detalhes não vão ser todos substituídos pelos detalhes da nova mesa (obtidos da BD)? Era suposto funcionar assim. Não há necessidade de remover todos os controls, basta alterar o conteúdo de cada um. E utilizas os mesmos controls para os detalhes de qualquer mesa.
     
  17. candycane

    candycane Power Member

    Também pensava k substituia... mas estao a ficar um em cima dos outros :(

    o que tenho no btn_atras é isto:

    private void btn_atras_Click(object sender, EventArgs e)
    {
    pnl_inicio.Visible =
    true;
    pnl_detalhes.Visible =
    false;
    }


    :(
     
  18. balute

    balute Power Member

    E na parte de preencher os detalhes para uma mesa, não estás a criar novos controls? Acho que esta é a única razão para aparecerem uns controls em cima dos outros...
     
  19. candycane

    candycane Power Member

    Tou sim, crio labels com os pedidos e botoes para mais detalhes. Fiz debug e os dados variam conforme a mesa que clico. Mas ficam em cima uns dos outros :(

    Código:
    if(conta == 0)
    {
    lbl_SemPedido.Visible = true;
    lbl_SemPedido.Text = "Não há pedidos para esta mesa.";
    }
    else
    {
    for (int i = 0; i < conta; i++)
    {
    sr.Read();
    lbl_Pedidos[i] = newLabel();
    btn_detalhes[i] = newButton();
    lbl_Pedidos[i].Location = newPoint(105, 120 + (i * 25));
    lbl_Pedidos[i].Text = sr["P_Mesa"].ToString();
    
    btn_detalhes[i].Location = newPoint(16, 118 + (i * 25));
    btn_detalhes[i].Text = "+ info";
    btn_detalhes[i].Size = newSize(48, 23);
    btn_detalhes[i].ForeColor = SystemColors.HotTrack;
    btn_detalhes[i].Font = newFont("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
    pnl_detalhes.Controls.Add(lbl_Pedidos[i]);
    pnl_detalhes.Controls.Add(btn_detalhes[i]);
    }
    }[SIZE=2]
    [/SIZE]
     
    Última edição pelo moderador: 25 de Maio de 2008
  20. balute

    balute Power Member

    Então é esse o problema. Se não houver nenhum inconveniente, devias usar sempre o mesmo conjunto de labels e botões para a apresentação dos detalhes. E esses labels/botões podem ser colocados durante o design.

    Se quiseres mesmo criar novos controls, também não há problema, podes sempre usar a subrotina que mostrei no post #14. Basta passá-la o pnl_detalhes como argumento, e todos os controls dentro do pnl_detalhes serão eliminados.
    Código:
    remover_controls(pnl_detalhes);
     

Partilhar esta Página