AJUDA COM DELEGETE

LUIS.HERRERA 08/11/2012 16:59:15
#413838
Boa tarde Pessoal.
Estou apanhando um pouco (muito) nesse assunto.

Tenho um MDIPai e vários forms filhos.
No MDI Pai criei:
- Um menu
- Um barra com botões de atalho para as principais telas
- Uma barra com botões padrão para todos os forms filhos: Incluir, Alterar, Salvar, etc...

No botão de atalho que chama um form filho, fiz assim:
private void btAbreFormFilho1_Click(object sender, EventArgs e)
{
// fiz uma classe que guarda todos os formulários abertos e assim posso controlar cada um
for (int i = 0; i < Program.Formularios.forms.Count; i++)
{
if (Program.Formularios.forms[i].Name == [Ô]frmFilho1[Ô]) //item = mesmo formulário que acabamos de solicitar a abertura
{
//se for então prepara para ao ser fechado tirar o ticado do menu
Program.Formularios.forms[i].Closed += delegate
{
this.cadastroToolStripMenuItem5.Checked = false;
this.btIncluir.Enabled = false;
this.btAlterar.Enabled = false;
this.btSalvar.Enabled = false;
this.btConsultar.Enabled = false;
this.btImprimir.Enabled = false;
this.btLimpar.Enabled = false;
[txt-color=#e80000]// PROBLEM AQUI estou querendo que ao clicar no botão Incluir do MDI Pai, ele execute a rotina bT_INCLUIR_Click do frmFilho1 mas não está funcionando nem com a mensagembox abaixo[/txt-color]
this.btIncluir.Click += delegate
{
MessageBox.Show([Ô]Clicou Incluir[Ô]);
};
};
break;
}
}
this.btIncluir.Enabled = true;
this.btAlterar.Enabled = true;
this.btConsultar.Enabled = true;
this.btLimpar.Enabled = true;
this.formAberto = [Ô]frmFilho1[Ô];
}

1_ o frmFilho1 terá o código de clique do botão Incluir, como se o botão estivesse no próprio form, e isso existirá para cada um dos botões em cada um dos formulários filho. ~
2_ os botões do MDI Pai terão que acionar suas respectivas rotinas nos formulários filhos, todos os eventos click terão o mesmo nome em cada formulário filho assim fica fácil padronizar:

IMPORTANTE: Posso restringir a ter só um formulário filho aberto por vez.

Como eu devo fazer para ao abrir o form filho (menu ou botão do form MDI Pai) informar aos outros botões Incluir, alterar, etc.. (também do form MDI Pai) que devem executar as rotinas no formulário que estiver aberto?

Obrigado.
KERPLUNK 08/11/2012 17:09:18
#413839
Tenta assim:
this.btIncluir.Click += FrmFormFilho.Button1_Click(this, null);
LUIS.HERRERA 09/11/2012 08:53:02
#413866
Kerplunk bom dia.

CONSEGUI VALEU !!!!

O botão do MDI Pai vai chamar uma função ou sub do Form Filho, que é por exemplo.

public static void Incluir()
{
MessageBox.Show([Ô]Consegui acessar a rotina do form filho![Ô]);
}

No form Pai incluí como disse:

this.btIncluir.Click += delegate { formFilho.Incluir(); };

e Voi lá.
Abraço e ótimo final de semana a todos.
LUIS.HERRERA 09/11/2012 10:27:27
#413876
Kerplunk ou amigos, surgiu outro problema agora.

Ao atribuir um delegate a um objeto ex:
this.btIncluir.Click += delegate { formFilho.Incluir(); };

Ele fica permanente durante a execução. Porém no meu caso eu terei alguns botões, onde cada um irá atribuir o delegate ao mesmo botão do MDI Pai. O problema é que os delegates estão sendo acrescentados e não substituídos.

A minha necessidade é ao clicar no botão Funcionários, o botão Incluir terá o delegate IncluirFuncionário, já quando clicar em outro botão para abrir Departamentos, o botão Incluir terá o delegate IncluirDepartamento e assim por diante, ou seja, o botão incluir só pode ter um único delegate e aquele atribuído por último.

Pesquisei e não descobri como substituir um delegate ou como excluir um já atribuido. Para excluir acho que existe o:
this.btIncluir.Click [txt-color=#e80000]-[/txt-color]= delegate { formFilho.Incluir(); }; // trocar o sinal do + pelo - (menos) o problema é que não tenho como saber qual o delegate foi associado e se algum foi, pois como não há uma sequência de abertura de formulários, para excluir teria de saber se já existe algum associado e qual é.

Como eu faça para resolver isso?
KERPLUNK 09/11/2012 10:58:36
#413883
Pelo que estou entendendo, você quer ter uma barra de ferramentas genérica que faz todas as ações para cada form, estou correto? Se for, você está indo pelo caminho errado. Pense OOP
LUIS.HERRERA 09/11/2012 12:38:12
#413898
Como assim estou no caminho errado?
Um Word , excel e muito outros aplicativos, tem uma barra genérica que possui ação sobre o documento aberto, ou seja, suas ações funcionam sobre o documento, seja ele qual for.

O que estou querendo fazer é isso, ter uma barra padrão para todas as telas. A idéia é justamente reduzir código, despoluir a tela, padronizar e ainda aumentar a área de utilização da tela para controles de dados e não botões que são os mesmos para qualquer form. Não entendo o que esteja errado nisso.

O problema é que a ação:
this.btIncluir.Click -= delegate { formFilho.Incluir(); };
ou
this.btIncluir.Click -= delegate {};

Não surte efeito, pois o delegate não está sendo retirado do evento click do botão, sendo executado todos. Ex:
Se eu clicar uma vez no botão Funcionários, ao abrir a tela e clicar no botão Incluir, é exibida uma vez a mensagem. Se eu fecho esta tela e abro novamente, surgem então duas mensagens e assim por diantes, se abrir outro form, abre duas vezes a mensagen do primeiro e uma do segundo forma.

Eu quero tirar o delegate atribuido em tempo de excução pelo botão, ao fechar o formulário que o criou. Só isso.

Por que o -= não retira o delegate como explicado na documentação?
KERPLUNK 09/11/2012 13:26:12
#413902
Citação:

Um Word , excel e muito outros aplicativos, tem uma barra genérica que possui ação sobre o documento aberto, ou seja, suas ações funcionam sobre o documento, seja ele qual for.


A idéia errada, não é a barra, isso está ok. O problema, é usar funcionalidades dentro do form filho. O que deve ser feito:
Cada coisa que você for abrir uma janela para editar, deve ser um objeto, que herda funcionalidades de uma interface genérica.
Vamos supor que você abra um cliente para editar. Cliente, é um objeto, uma classe, que vai herdar métodos como Update, Inserir, Deletar... Pois bem, o que você deve fazer, é em cada form, ter uma propriedade de classe que vai ser uma instância do objeto. O botão da barra de genérica(como o [Ô]grava[Ô], por exemplo), não vai ter um delegate para um método dentro do form. Ele vai ter um delegate para um método dentro da classe do objeto que está aberto na janela. Então, a janela em si, é um mero [Ô]observador[Ô], o que realmente é funcional é a classe de cliente, é nela que os métodos de gravação devem estar.
LUIS.HERRERA 09/11/2012 14:33:10
#413916
Kerplunk NÃO é o botão padrão INCLUIR do MDI Pai que irá realizar o método de incluir no banco. Ele, ao ser clicado, deve somente acionar um método no formulário aberto. Este método, do form filho, que terá o nome IncluirAlgumaCoisa, irá acionar o objeto da classe DAL e acionar seu método Incluir, ou seja, o formulário Funcionário, dispara o método IncluirFuncionario que irá chamar o objeto da Classe Funcionário e este sim usará o seu método privado de incluir os dados do funcionário, tudo como o OOP prega. Isso depois de fazer a validação da classe BLL.....

Então o objetivo que tenho é somente fazer os botões genéricos para chamar um método intermediário e específico do formulário aberto e este se encarrega de acionar o objeto correto. Entendeu?

Classe Modelo
Classe DAL (métodos, consultar, incluir, alterar, excluir, etc...)
Classe BLL (validações, etc...)
Tela Usuário (aqui terá toda licação com os objetos das classes acima respectivamente as suas tabelas através de um método acionado pelo botão do MDI PAI)

MDI Pai (este controla tudo pelo menu, barra com botões de atalho e barra com botões Padrão = Incluir, Alterar, etc..como se fosse um Word da vida)

O que já está funcionando:

No MDI Pai ao clicar no menu / ou botões de atalho:
- abro os forms filhos e controle o formulário que foi aberto através de uma lista;
- Crio os delegates para o método fechar do form filho que contém (tirar o tickiet do item do menu, colocar os botões padrão com enabled = false, entre outras ações).
- habilito (enabled = true) para os botões padrão (incluir, alterar,etc...) do MDI pai
- Atribuo o delegate ao botão padrão incluir que chama um método do form filho que no momento exibe apenas uma messgeBox, mas depois irá chamar o método da classe de acesso a dados desta tela.

O que não está funcionando (apesar de não dar nenhum erro):
- botão de atalho que abre o formulário, tem a rotina de controle dos fomulários já abertos (LISTA) e nela que defino o delegate usado no Closed do formulário e as outras ações do evento, como abiaxo.
Na parte em vermelho a tentativa de remover o delegate do botão padrão Incluir é que não está funcionando, e não sei o porque já que a documentação diz que para remover um delegate se usa -=

private void btAbreFormFilho1_Click(object sender, EventArgs e)
{
// fiz uma classe que guarda todos os formulários abertos e assim posso controlar cada um
for (int i = 0; i < Program.Formularios.forms.Count; i++)
{
if (Program.Formularios.forms[i].Name == [Ô]frmFilho1[Ô]) //item = mesmo formulário que acabamos de solicitar a abertura
{
//se for então prepara para ao ser fechado tirar o ticado do menu
Program.Formularios.forms[i].Closed += delegate
{
this.cadastroToolStripMenuItem5.Checked = false;
[txt-color=#e80000]this.btIncluir.Click -= delegate { formFilho.Incluir(); }; [/txt-color] // não está reconhecento, será que tem algo com o GAC?
this.btIncluir.Enabled = false;
this.btAlterar.Enabled = false;
this.btSalvar.Enabled = false;
this.btConsultar.Enabled = false;
this.btImprimir.Enabled = false;
this.btLimpar.Enabled = false;
};
break;
}
}
this.btIncluir.Click += delegate { formFilho.Incluir(); }; [txt-color=#0000f0]//informa qual método do Form Filho o botão incluir do MDI pai vai executar (OK Funciona)[/txt-color]
this.btIncluir.Enabled = true;
this.btAlterar.Enabled = true;
this.btConsultar.Enabled = true;
this.btLimpar.Enabled = true;
this.formAberto = [Ô]frmFilho1[Ô];
}

Como Eu excluo um Delegate Atribuido?


Nota: Pesquisando, achei um post que pode ser muito interessantes para algusn. Confesso que isso está acima do meu conhecimento ainda e não entendi quase nada.

http://msdn.microsoft.com/pt-br/magazine/cc163533.aspx
LUIS.HERRERA 12/11/2012 10:33:03
#414030
Caros amigos venho compartilhar com todos a descoberta que fiz, após muitas e muitas pesquisas em 10 dias na web. Já estava perdendo as esperanças, pois não encontrava solução ou respostas.

Pois bem, quando você cria um delegate é criado um objeto para ele. Então se nesse evento ou método que está criando o delegate você usar duas vezes ou mais a mesma expressão delegate, por mais idêntico que seja o parâmetro usado, será sempre criado um novo objeto. EX:

btIncluir.Click += delegate {Calcular();}; // incluindo o método (funciona, mas a cada execução do btIncluir.Click terá o método calcular duplicado.

e depois

btIncluir.Click -= delegate {Calcular();}; // retirando o método [txt-color=#e80000](Não Funciona)[/txt-color]

O seu aplicativo terá 2 objetos com referência so método Calcular totalmente distintos, e assim é impossível remover um delegate. Então qual a solução?

Veja abaixo:

EventHandler d = delegate {Calcular();};

No lugar que quiser usar, coloca:

btIncluir.Click += d;

e

btIncluir.Click -= d; // [txt-color=#0000f0]Agora Funciona[/txt-color]

Certamente alguém futuramente terá esse problema e espero que ache este tópico rapidamente.

Boa semana a todos.
Tópico encerrado , respostas não são mais permitidas