none
Controle Adicionado "Dinamicamente", inicializado no método "OnInit" não dispara eventos RRS feed

  • Pergunta

  • Bom dia,

    escrevi estas classes (que derivam de várias outras e implementam diversas interfaces que escrevi) porém, mesmo iniciando o controle "filho" no método sobrescrito "OnInit", e atribuindo neste momento o evento ao controle, o mesmo não dispara o evento associado. Nenhum dos 3 itens propostos (2 botões e 1 REPEATER!!).

    Por favor, vejam o código abaixo (PS: Muitos namespaces aparecerão - estes são próprios).

    namespace Info
            {
                public sealed class StringArrayConverter : Sys.ComponentModel.TypeConverter //http://stackoverflow.com/questions/116797/passing-int-array-as-parameter-in-web-user-control
                {
                    public override bool CanConvertFrom(Sys.ComponentModel.ITypeDescriptorContext context, Sys.Type sourceType) { return sourceType == typeof(string); }
                    private string[] Spliter(string value) { if (value == null || value == "") { return new string[] { }; } else { return value.Split(new string[] { "||" }, Sys.StringSplitOptions.RemoveEmptyEntries); } }
                    public override object ConvertFrom(Sys.ComponentModel.ITypeDescriptorContext context, Sys.Globalization.CultureInfo culture, object value) { return this.Spliter(value as string); }
                }
    
                public class Template : SysWeb.UI.ITemplate //https://msdn.microsoft.com/en-us/library/aa289501(v=vs.71).aspx
                {
                    public string IdFieldName { get; set; }
                    public string LabelFieldName { get; set; }
    
                    protected void Label_DataBinding(object sender, Sys.EventArgs e)
                    {
                        SysWCt.Literal nLc = (SysWCt.Literal)sender;
                        nLc.Text += NFlds.String.Read((SysWCt.RepeaterItem)nLc.NamingContainer, this.LabelFieldName);
                    }
    
                    private void Button_DataBinding(object sender, Sys.EventArgs e)
                    {
                        MdWeb.Controls.Button nBt = (MdWeb.Controls.Button)sender;
                        nBt.CommandArgument = NFlds.Integer.Read((SysWCt.RepeaterItem)nBt.NamingContainer, this.IdFieldName);
                    }
    
                    protected SysWCt.Literal CreateLiteral(string Text, bool Handled)
                    {
                        SysWCt.Literal nLc = new SysWCt.Literal();
                        nLc.Text = Text;
                        if (Handled) { nLc.DataBinding += this.Label_DataBinding; }
                        return nLc;
                    }
    
                    protected MdWeb.Controls.Button CreateButton(string Name, MdWeb.Controls.Button.Behaving Behave)
                    {
                        MdWeb.Controls.Button nBt = new MdWeb.Controls.Button();
                        nBt.ID = Name;
                        nBt.CommandName = Name;
                        nBt.Behave = Behave;
                        nBt.DataBinding += this.Button_DataBinding;
                        return nBt;
                    }
    
                    public void InstantiateIn(SysWeb.UI.Control Container)
                    {
                        Container.Controls.Add(this.CreateLiteral("<li><div class=\"control\">", false));
                        Container.Controls.Add(this.CreateButton(MdWeb.Controls.PickerSearch.SelectKey, MdWeb.Controls.Button.Behaving.IcoSelect));
                        Container.Controls.Add(this.CreateButton(MdWeb.Controls.PickerSearch.DeleteKey, MdWeb.Controls.Button.Behaving.IcoDelete));
                        Container.Controls.Add(this.CreateLiteral("</div><div>", false));
                        Container.Controls.Add(this.CreateLiteral("<b>" + MdCORE.Labels.Front.Item + ":</b>", true));
                        Container.Controls.Add(this.CreateLiteral("</div></li>", false));
                    }
    
                    public Template(string IdFieldName, string LabelFieldName)
                    {
                        this.IdFieldName = IdFieldName;
                        this.LabelFieldName = LabelFieldName;
                    }
                }
    
                public abstract class Panel<TRec, TTarget> : SysWeb.UI.Control, MdWeb.Pages.Blocks.IDependent, SysWeb.UI.IPostBackDataHandler where TRec : NRecs.Parent, NRecs.ILabeled, NRecs.IParented<TTarget>, new() where TTarget : NRecs.Record, new()
                {
                    public MdWeb.Pages.WebPage MainPage { get { return (MdWeb.Pages.WebPage)this.Page; } }
                    public MdCORE.User SData { get { return this.MainPage.SData; } }
                    public void Alert(string Message) { MdWeb.WebObject.Alert(Message, this.Page); }
                    public bool Alert(bool TestToExit, string Message) { return MdWeb.WebObject.Alert(TestToExit, Message, this.Page); }
                    public abstract string Label { get; }
                    public event MdWeb.Pages.Blocks.BackEventHandler Back;
                    private const string PickerID = "Picker";
                    private const string AddButtonID = "AddButton";
                    private const string BackButtonID = "BackButton";
                    private const string RootKey = "root";
                    private const string RecKey = "rec";
                    private const string DataKey = "dtable";
                    [Sys.ComponentModel.TypeConverter(typeof(MdWeb.Pages.Info.StringArrayConverter))] public string[] Labels { get; set; }
                    public decimal Selected { get { return (decimal)this.ViewState[MdWeb.Pages.Info.Panel<TRec, TTarget>.RootKey]; } set { this.ViewState[MdWeb.Pages.Info.Panel<TRec, TTarget>.RootKey] = value; } }
                    public TRec Record { get { return (TRec)this.ViewState[MdWeb.Pages.Info.Panel<TRec, TTarget>.RecKey]; } }
                    public SysDt.DataTable Data { get { return (SysDt.DataTable)this.ViewState[MdWeb.Pages.Info.Panel<TRec, TTarget>.DataKey]; } set { this.ViewState[MdWeb.Pages.Info.Panel<TRec, TTarget>.DataKey] = value; } }
                    private SysClG.Dictionary<string, MdWeb.Controls.Generic.FieldControl> ChildControls { get; set; }
                    private void InvokeBack() { if (this.Back != null) { this.Back(); } }
                    protected MdWeb.Controls.PickerSearch Picker;
                    protected MdWeb.Controls.Button AddNew;
                    protected MdWeb.Controls.Button BackButton;
                    void SysWeb.UI.IPostBackDataHandler.RaisePostDataChangedEvent() { /* NOTHING */ }
                    public virtual void PostBackLoad() { /* NOTHING */ }
                    public virtual void CreateForm() { /* NOTHING */ }
                    public abstract void SaveData();
                    protected virtual bool LabelsMatch() { return (this.Labels != null && this.Labels.Length == (this.Record.Count() - 1)); } //'-1 due to root key
    
                    private void CreateControl<TControl>(TControl Control, string Name, int Pos, bool LabelsMatched) where TControl : MdWeb.Controls.Generic.FieldControl
                    {
                        Control.ID = Name;
                        Control.Label = (LabelsMatched ? this.Labels[Pos] : "Field (" + Pos.ToString() + ")");
                        this.ChildControls.Add(Name, Control);
                    }
    
                    private void OnSave(object sender, Sys.EventArgs e)
                    {
                        if (this.Selected != NFlds.Integer.Empty)
                        {
                            ((NRecs.IParented<TTarget>)this.Record).Root.SetValue(this.Selected, true);
                            foreach (SysClG.KeyValuePair<string, MdWeb.Controls.Generic.FieldControl> KeyPair in this.ChildControls)
                            {
                                NFlds.Field Field = this.Record[KeyPair.Key];
                                if (Field == null)
                                {
                                    this.Alert(MdCORE.Labels.Messages.ErrorFieldNotFoundED49);
                                    return;
                                }
                                else
                                {
                                    Field.Obj = KeyPair.Value.Obj;
                                    Field.Postable = KeyPair.Value.Postable;
                                }
                            }
                            if (((NRecs.ILabeled)this.Record).Label == null || ((NRecs.ILabeled)this.Record).Label == "") { this.Alert(MdCORE.Labels.Messages.ErrorNoPostableDataED04); } else { this.SaveData(); }
                        }
                    }
    
                    private void ClearPanel()
                    {
                        this.Record.Clear();
                        foreach (SysClG.KeyValuePair<string, MdWeb.Controls.Generic.FieldControl> KeyPair in this.ChildControls) { KeyPair.Value.SetEmpty(); }
                    }
    
                    private void OnBack(object sender, Sys.EventArgs e)
                    {
                        this.ClearPanel();
                        this.InvokeBack();
                    }
    
                    private void AddTextBox(NFlds.Field Field, int Pos, bool LabelsMatched)
                    {
                        MdWeb.Controls.TextString Box = new MdWeb.Controls.TextString();
                        this.CreateControl(Box, Field.Name, Pos, LabelsMatched);
                        Pos = (Field as NFlds.String).MaxSize;
                        if (Pos > 0) { Box.MaxLength = Pos; }
                    }
    
                    private void CreateControls(bool LabelsMatched)
                    {
                        int Pos = 0;
                        string RootName = (this.Record as NRecs.IParented<TTarget>).Root.Name;
                        foreach (NFlds.Field Field in this.Record)
                        {
                            if (Field.Name != RootName)
                            {
                                Sys.Type TypeOf = Field.GetType();
                                if (TypeOf != typeof(NFlds.Foreign<>) && TypeOf != typeof(NFlds.NullForeign<>) && TypeOf != typeof(NFlds.DateTime) && TypeOf != typeof(NFlds.DblDateTime) && TypeOf != typeof(NFlds.Optional))
                                {
                                    if (TypeOf == typeof(NFlds.Boolean)) { this.CreateControl(new MdWeb.Controls.Check(), Field.Name, Pos, LabelsMatched); }
                                    else if (TypeOf == typeof(NFlds.String)) { this.AddTextBox(Field, Pos, LabelsMatched); }
                                    else if (TypeOf == typeof(NFlds.Integer) || TypeOf == typeof(NFlds.NullInteger)) { this.CreateControl(new MdWeb.Controls.TextInteger(), Field.Name, Pos, LabelsMatched); }
                                    else if (TypeOf == typeof(NFlds.Double) || TypeOf == typeof(NFlds.NullDouble) || TypeOf == typeof(NFlds.Money) || TypeOf == typeof(NFlds.NullMoney)) { this.CreateControl(new MdWeb.Controls.TextDouble(), Field.Name, Pos, LabelsMatched); }
                                    else if (TypeOf == typeof(NFlds.Double) || TypeOf == typeof(NFlds.NullDouble)) { this.CreateControl(new MdWeb.Controls.TextDouble(), Field.Name, Pos, LabelsMatched); }
                                    else if (TypeOf == typeof(NFlds.Date) || TypeOf == typeof(NFlds.IntDate)) { this.CreateControl(new MdWeb.Controls.TextCalendar(), Field.Name, Pos, LabelsMatched); }
                                    else if (TypeOf == typeof(NFlds.DblTime)) { this.CreateControl(new MdWeb.Controls.TextTime(), Field.Name, Pos, LabelsMatched); }
                                    Pos++;
                                }
                            }
                        }
                    }
    
                    private void LoadPanel()
                    {
                        try
                        {
                            foreach (SysClG.KeyValuePair<string, MdWeb.Controls.Generic.FieldControl> Pair in this.ChildControls)
                            {
                                Pair.Value.Obj = this.Record[Pair.Key].Obj;
                                Pair.Value.Postable = false;
                            }
                        } catch { this.ClearPanel(); }
                    }
    
                    private void LoadPanel(decimal Id) { if (this.Selected != NFlds.Integer.Empty && this.Record.Load(this.MainPage.Dbm, Id)) { this.LoadPanel(); } else { this.ClearPanel(); } }
    
                    protected virtual void SearchData() { this.Data = NView.View.Search(this.MainPage.Dbm, this.Record, Distinct: false, Limit: 0, WhereArgs: new NView.Where.Args(((NRecs.IParented<TTarget>)this.Record).Root.EqualArg(this.Selected.ToString(), false)), OrderBy: default(NView.OrderBy), Joins: null); }
    
                    private void OnItemCommand(object source, SysWCt.RepeaterCommandEventArgs e)
                    {
                        decimal Id = MdWeb.Controls.PickerSearch.GetSelection(e);
                        if (Id == NFlds.Integer.Empty) { this.Alert(MdLbl.Messages.ErrorNoIndexED14); }
                        {
                            if (e.CommandName == MdWeb.Controls.PickerSearch.SelectKey) { this.LoadPanel(Id); }
                            else if (e.CommandName == MdWeb.Controls.PickerSearch.DeleteKey)
                            {
                                if (this.SData.Delete<TRec>(this.MainPage.Dbm, this.Record))
                                {
                                    this.ClearPanel();
                                    this.SearchData();
                                    this.Picker.Bind(this.Data);
                                } else { this.Alert(MdLbl.Messages.ErrorDeleteRecordED46); }
                            } else { this.Alert(MdLbl.Messages.ErrorKeyInvalidED27); }
                        }
                    }
    
                    protected virtual SysWeb.UI.ITemplate CreateItemTemplate() { return new MdWeb.Pages.Info.Template(this.Record.Id.Name, this.Record.Label.Name); }
    
                    private void CreateUI()
                    {
                        this.Picker = new MdWeb.Controls.PickerSearch();
                        this.Picker.ItemCommand += this.OnItemCommand;
                        this.Picker.ID = MdWeb.Pages.Info.Panel<TRec, TTarget>.PickerID;
                        this.Picker.EnableViewState = true;
                        this.AddNew = new MdWeb.Controls.Button();
                        this.AddNew.Click += this.OnSave;
                        this.AddNew.ID = MdWeb.Pages.Info.Panel<TRec, TTarget>.AddButtonID;
                        this.AddNew.Behave = MdWeb.Controls.Button.Behaving.SaveAction;
                        this.AddNew.Style.Add("margin-right", "6px");
                        this.AddNew.Style.Add("float", "left");
                        this.BackButton = new MdWeb.Controls.Button();
                        this.BackButton.Click += this.OnBack;
                        this.BackButton.ID = MdWeb.Pages.Info.Panel<TRec, TTarget>.BackButtonID;
                        this.BackButton.Behave = MdWeb.Controls.Button.Behaving.BackAction;
                        this.ChildControls = new SysClG.Dictionary<string, MdWeb.Controls.Generic.FieldControl>();
                    }
    
                    private void BindUI()
                    {
                        this.Picker.ItemTemplate = this.CreateItemTemplate();
                        this.CreateControls(this.LabelsMatch());
                    }
    
                    private void AddViewState(TRec item, decimal Id, SysDt.DataTable DTable)
                    {
                        this.ViewState.Add(MdWeb.Pages.Info.Panel<TRec, TTarget>.RootKey, NFlds.Integer.Empty);
                        this.ViewState.Add(MdWeb.Pages.Info.Panel<TRec, TTarget>.DataKey, new SysDt.DataTable());
                        this.ViewState.Add(MdWeb.Pages.Info.Panel<TRec, TTarget>.RecKey, item);
                    }
    
                    private void AddPair(Sys.Collections.ArrayList lst, string Key, object Value)
                    {
                        lst.Add(Key);
                        lst.Add(Value);
                    }
    
                    protected override void OnInit(Sys.EventArgs e)
                    {
                        this.CreateUI();
                        if (!this.Page.IsPostBack)
                        {
                            this.AddViewState(new TRec(), NFlds.Integer.Empty, new SysDt.DataTable());
                            this.BindUI();
                        }
                        base.OnInit(e);
                    }
    
                    protected override void OnLoad(Sys.EventArgs e)
                    {
                        base.OnLoad(e);
                        this.DataBind();
                    }
    
                    protected override object SaveViewState()
                    {
                        Sys.Collections.ArrayList lst = new Sys.Collections.ArrayList();
                        this.AddPair(lst, MdWeb.Pages.Info.Panel<TRec, TTarget>.RootKey, this.Selected);
                        this.AddPair(lst, MdWeb.Pages.Info.Panel<TRec, TTarget>.RecKey, this.Record);
                        this.AddPair(lst, MdWeb.Pages.Info.Panel<TRec, TTarget>.DataKey, this.Data);
                        return new SysWeb.UI.Pair(lst, null);
                    }
    
                    protected override void LoadViewState(object savedState)
                    {
                        try
                        {
                            Sys.Collections.ArrayList lst = ((savedState as SysWeb.UI.Pair).First as Sys.Collections.ArrayList);
                            for (int i = 0; i < lst.Count - 1; i = i + 2) { this.ViewState.Add((string)lst[i], lst[i + 1]); }
                            this.LoadPanel();
                            this.BindUI();
                            lst.Clear();
                            lst = null;
                            this.Picker.Bind(this.Data);
                        } catch { this.Alert(MdCORE.Labels.Messages.ErrorInfoPanelViewStateED50(this.ID)); }
                    }
    
                    public bool LoadPostData(string postDataKey, global::System.Collections.Specialized.NameValueCollection postCollection)
                    {
                        foreach (string Key in postCollection) { this.ChildControls[Key].Obj = postCollection[Key]; }
                        return true;
                    }
    
                    public virtual void Clear()
                    {
                        this.Selected = NFlds.Integer.Empty;
                        this.ClearPanel();
                    }
    
                    public virtual void LoadSelection()
                    {
                        if (this.Selected != NFlds.Integer.Empty)
                        {
                            this.SearchData();
                            this.Picker.Bind(this.Data);
                        } else { this.Clear(); }
                    }
    
                    protected override void Render(SysWeb.UI.HtmlTextWriter writer)
                    {
                        writer.Write("<b>" + this.Label + "</b><br /><div><ul class=\"bindedinfo\">");
                        this.Picker.RenderControl(writer);
                        writer.Write("</ul></div><div>");
                        foreach (SysClG.KeyValuePair<string, MdWeb.Controls.Generic.FieldControl> KeyPair in this.ChildControls) { KeyPair.Value.RenderControl(writer); }
                        this.AddNew.RenderControl(writer);
                        this.BackButton.RenderControl(writer);
                        writer.Write("</div>");
                    }
                }
            }
    		
    		public class Processor : MdWeb.Pages.Info.Panel<MdSet.DEV.Components.Processors, MdSet.DEV.Devices>
    		{
    		    public override string Label { get { return MdCORE.Labels.Front.Processor; } }
    			public override void SaveData() { this.Record.Save(this.MainPage.Dbm); }
    		}

    Desde já agradeço.

    terça-feira, 20 de outubro de 2015 15:46

Respostas

  • Opa, tudo bom SammuelMiranda?

    Vi que vocês já revisaram bastante coisa, e posso estar sendo redundante, mas você já testou acrescentar os eventos de outra forma, por exemplo, acrescentar um método anônimo simples invés do EventHandler pra ver se ocorre o mesmo comportamento, ou então acrescentar o método do EventHandler como um new EventHandler?

        protected MdWeb.Controls.Button CreateButton( string Name, MdWeb.Controls.Button.Behaving Behave )
            {
                MdWeb.Controls.Button nBt = new MdWeb.Controls.Button();
                nBt.ID = Name;
                nBt.CommandName = Name;
                nBt.Behave = Behave;
                nBt.DataBinding += new EventHandler(this.Button_DataBinding);
                return nBt;
            }

    Ou então:

        protected MdWeb.Controls.Button CreateButton( string Name, MdWeb.Controls.Button.Behaving Behave )
            {
                MdWeb.Controls.Button nBt = new MdWeb.Controls.Button();
                nBt.ID = Name;
                nBt.CommandName = Name;
                nBt.Behave = Behave;
                nBt.DataBinding += (s,e) => { MessageBox.Show("Seu evento funcionou!") };
                return nBt;
            }


    Enfim, dá uma olhada nesses exemplos, você tem bastante elemento herdando de outras classes nativas e muita coisa criada de forma dinâmica. Em ambientes onde você tem esse grau de complexidade problemas como este podem aparecer, e geralmente é alguma coisa muito simples que resolve, o problema é identificar no emaranhado do fluxo do programa ^^

    Boa sorte cara, se eu descobrir alguma coisa eu volto a postar nessa thread.

    EDIT: Cara, dá uma olhada na thread dese maluco aqui, acho que o problema era parecido, e a forma como ele resolveu pode te ajudar:

    How to add event handlers to dynamic controls


    • Editado Samuel Pelaquim sexta-feira, 30 de outubro de 2015 18:21 Colei o link direto, esuqeci que é MSDN...
    • Sugerido como Resposta SimorC domingo, 1 de novembro de 2015 22:56
    • Marcado como Resposta Marcos SJ segunda-feira, 2 de novembro de 2015 10:52
    • Não Marcado como Resposta SammuelMiranda terça-feira, 3 de novembro de 2015 10:37
    • Marcado como Resposta SammuelMiranda terça-feira, 3 de novembro de 2015 11:39
    sexta-feira, 30 de outubro de 2015 18:17
  • Tudo Resolvido. Bastou colocar "this.Page.RegisterRequiresPostBack(this);" na primeira linha no "OnInit()" e ajustar o método "LoadPostData" para pegar as chaves certas. Tudo correto, graças ao input do chara. Obrigado Samuel.

    public bool LoadPostData(string postDataKey, global::System.Collections.Specialized.NameValueCollection postCollection)
    {
        postDataKey += this.IdSeparator;
        foreach (SysClG.KeyValuePair<string, MdWeb.Controls.Generic.FieldControl> KeyPair in this.ChildControls) { KeyPair.Value.Obj = postCollection[postDataKey + KeyPair.Key]; }
        return true;
    }

    Além disso, no método "CreateControls()" coloquei "this.Controls.Add(Control)" também, ficou assim:

    private void CreateControl<TControl>(TControl Control, string Name, int Pos, bool LabelsMatched) where TControl : SysWeb.UI.Control, MdWeb.Controls.Generic.FieldControl
    {
        Control.ID = Name;
        Control.Label = (LabelsMatched ? this.Labels[Pos] : "Field (" + Pos.ToString() + ")");
        this.ChildControls.Add(Name, Control);
        this.Controls.Add(Control);
    }

    • Marcado como Resposta SammuelMiranda terça-feira, 3 de novembro de 2015 11:39
    terça-feira, 3 de novembro de 2015 11:39

Todas as Respostas

  • Boa tarde Sammuel,

    Você debugando o código conseguiu navegar pelos métodos?

    De uma olhada nesse exemplo: Utilizando delegates e eventos com user controls

    Atenciosamente, Roberto Alves

    quinta-feira, 22 de outubro de 2015 16:11
  • Boa tarde, SammuelMiranda.

    Olhando o código ficou uma dúvida.

    Os botões que não estão disparando eventos são esses:

    Container.Controls.Add(this.CreateButton(MdWeb.Controls.PickerSearch.SelectKey, MdWeb.Controls.Button.Behaving.IcoSelect));
    Container.Controls.Add(this.CreateButton(MdWeb.Controls.PickerSearch.DeleteKey, MdWeb.Controls.Button.Behaving.IcoDelete));

    Ou esses:

    this.AddNew = new MdWeb.Controls.Button();
    this.BackButton = new MdWeb.Controls.Button();


    Att., Rafael Simor

    quinta-feira, 22 de outubro de 2015 17:44
  • Rafael, boa tarde.

    Nenhum na verdade. Os botões feitos em "CreateButton(SelectKey)" e "CreateButton(DeleteKey)" fazem parte do repeater "Picker", que assim como "AddNew" (botão) e "BackButton", tem eventos associados que não disparam.

    quinta-feira, 22 de outubro de 2015 17:52
  • Roberto, boa tarde. "Navegar pelos métodos" eu não entendi. Ao debugar o controle dispara "OnInit()" (o USERCONTROL, o container), cria os controles filhos e associa eventos as eles. Os eventos associados não disparam, esse é o problema.
    quinta-feira, 22 de outubro de 2015 17:54
  • Bom, tenho algumas ideias:

    - Como o Roberto já havia falado, coloque um breaking point no teu OnInit() e dê F10/F11, verificando linha por linha; para melhor entender o problema.

    - Verifique se a ViewState da Page/UserControl (até mesmo web.config) está como true.

    - Verifique se os eventos não estão se perdendo no PostBack.

    - Verifique pelo debugger do navegador se não está gerando nenhum erro ao clicar no botão.

    - Verifique se os ID's gerados dos controles estão corretos.

    - Verifique se os Behaviors desses controles estão corretamente configurados.

    Pessoalmente, se nada desse certo, eu criaria um UserControl de "teste", adicionando os controles dinamicamente (nativos do ASP.NET); colocaria um breaking point e compararia os valores de ambos formulários, verificando se não existe alguma discrepância muito grande nas propriedades da Página e dos Controles.


    Att., Rafael Simor

    quinta-feira, 22 de outubro de 2015 18:20
  • SimorC, bom dia.

    Ponto a ponto:

    - Já fiz o break point no OnInit(): o OnInit() é executado, chama o metodo "CreateUI()" (que cria o Repeater e os botões e associa eventos a eles). Esses eventos não são disparados no entanto, o que é o meu problema (já botei break nos handlers deles).

    - O ViewState está "funcionando" corretamente. Os métodos "SaveViewState()" e "LoadViewState()" são chamados e executados restaurando as chaves que criei. Os controles são criados novamente no "OnInit()", antes do ViewState ser carregado pois os controles não ficam gravados no ViewState.

    - Como verifico se o evento se "perdeu" no Postback?

    - Todos os controles são criados, com MESMO ID sempre, no método "CreateUI()", ativado durante o "OnInit()".

    - Behavior é uma propriedade que eu criei, que é basicamente uma substituição do atributo "CssClass", apenas para eu não ter que digitar a classe CSS do botão, facilitando os filtros.

    Esse código deriva de UserControl já. Deriva de uma classe que deriva do UserControl. Fiz isso apenas para disponibilizar mais métodos a todos os meus UserControls, com "Alert(string)" ... nada que afete os eventos ou Init ou Load do controle.

    sexta-feira, 23 de outubro de 2015 10:31
  • Bom dia, SammuelMiranda.

    Poderia nos informar se os botões estão ao menos disparando o PostBack?

    Este UserControl está sendo utilizado dentro de um UpdatePanel?

    Outra ideia:

    - Coloque esta linha do evento OnInit() no começo, não no final:

    base.OnInit(e);


    Att., Rafael Simor

    sexta-feira, 23 de outubro de 2015 14:09
  • Você se refere a essa parte:

    protected override void OnInit(Sys.EventArgs e)
                    {
                        this.CreateUI();
                        if (!this.Page.IsPostBack)
                        {
                            this.AddViewState(new TRec(), NFlds.Integer.Empty, new SysDt.DataTable());
                            this.BindUI();
                        }
                        base.OnInit(e);
                    }

    Se sim, já tentei o "base.OnInit(e);" no começo (primeira chamada do método) mas mesmo assim sem sucesso. Agora não, ele não está dentro de um UpdatePanel, está em uma Page (System.Web.Page).

    Agora quanto ao Postback, não entendi sua pergunta. Não, ele não dispara no postback, nem mesmo o método "bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)" está sendo acionado...

    sexta-feira, 23 de outubro de 2015 16:36
  • Boa tarde.

    Poderias tentar criar o botão diretamente no OnInit()?

    Algo do tipo:

    protected override void OnInit(Sys.EventArgs e)
                    {
                        // TODO: Coloque um breaking point aqui para verificar se o botão está ao menos gerando Postback
                        base.OnInit(e);
                        Button btnTeste = new Button
                        {
                            Text = "Testar"
                        };
                        btnTeste.Click += btnTeste_OnClick;
                        // TODO: Adicionar botão na página
    
    
                        //this.CreateUI();
                        //if (!this.Page.IsPostBack)
                        //{
                        //    this.AddViewState(new TRec(), NFlds.Integer.Empty, new SysDt.DataTable());
                        //    this.BindUI();
                        //}
                    }
    
                    protected void btnTeste_OnClick(object sender, EventArgs e)
                    {
                        // TODO: Coloque um breaking point neste evento somente para ver se ele será chamado
                    }

    Vamos tentar fazer funcionar do jeito mais simples possível. Se funcionar, deve ser algum problema de lógica (ordem de criação dos controles, possivelmente). Se não funcionar, é provável que o problema esteja no container (como a página está tratando os Postbacks, algum Id/ViewState que a página não esteja mantendo, etc.).


    Att., Rafael Simor

    sexta-feira, 23 de outubro de 2015 17:58
  • Oi SimorC, então o método "CreateUI()" faz isso:

    private void CreateUI()
                    {
                        this.Picker = new MdWeb.Controls.PickerSearch();
                        this.Picker.ItemCommand += this.OnItemCommand;
                        this.Picker.ID = MdWeb.Pages.Info.Panel<TRec, TTarget>.PickerID;
                        this.Picker.EnableViewState = true;
                        this.AddNew = new MdWeb.Controls.Button();
                        this.AddNew.Click += this.OnSave;
                        this.AddNew.ID = MdWeb.Pages.Info.Panel<TRec, TTarget>.AddButtonID;
                        this.AddNew.Behave = MdWeb.Controls.Button.Behaving.SaveAction;
                        this.AddNew.Style.Add("margin-right", "6px");
                        this.AddNew.Style.Add("float", "left");
                        this.BackButton = new MdWeb.Controls.Button();
                        this.BackButton.Click += this.OnBack;
                        this.BackButton.ID = MdWeb.Pages.Info.Panel<TRec, TTarget>.BackButtonID;
                        this.BackButton.Behave = MdWeb.Controls.Button.Behaving.BackAction;
                        this.ChildControls = new SysClG.Dictionary<string, MdWeb.Controls.Generic.FieldControl>();
                    }

    e ele é chamado no método sobrescrito "OnInit()" da classe abstrata "Panel<>" assim:

    protected override void OnInit(Sys.EventArgs e)
                    {
                        this.CreateUI();
                        if (!this.Page.IsPostBack)
                        {
                            this.AddViewState(new TRec(), NFlds.Integer.Empty, new SysDt.DataTable());
                            this.BindUI();
                        }
                        base.OnInit(e);
                    }

    já tirei o código do "CreateUI()" e escrevi direto no "OnInit()" como você sugeriu e já coloquei breakpoints em ambos os métodos "Click" e "ItemCommand" e no "OnInit". O "OnInit" breca e debuga, mas ele NUNCA DISPARA o "Click" ou "ItemCommand". Exemplo, o botão "BackButton" é associoado ao método "OnBack" descrito por:

    private void OnBack(object sender, Sys.EventArgs e)
                    {
                        this.ClearPanel();
                        this.InvokeBack();
                    }

    Um breakpoint nesse método NUNCA é acessado pelo debug.

    sexta-feira, 23 de outubro de 2015 18:11
  • Pois então, Sammuel, já havia percebido que os métodos criavam os controles e tudo o mais, porém, para identificar o problema, é melhor reduzir um pouco o "escopo", digamos assim.

    Colocando um botão extremamente simples direto no OnInit() e verificando que nem mesmo assim os eventos (no caso, btnTeste_OnClick) funcionam, conseguimos saber que o problema não está no "caminho" que teu código percorre.

    A maioria dos erros que eu não faço nem ideia do que está acontecendo eu tento simplificar ao máximo. Normalmente consigo identificar mais facilmente.

    Criei um exemplo aqui que funciona tranquilamente:

    UserCtrl.ascx.cs

    namespace AspNetDynamicControlEvents
    {
        public partial class UserCtrl : System.Web.UI.UserControl
        {
            protected void Page_Load(object sender, EventArgs e)
            {
    
            }
    
            protected void Page_Init(object sender, EventArgs e)
            {
                Button btnTest = new Button { Text = "Do it for glory" };
                btnTest.Click += btnTeste_OnClick;
    
                pnlControls.Controls.Add(btnTest);
            }
    
            protected void btnTeste_OnClick(object sender, EventArgs e)
            {
                lblTest.Text += " go ";
            }
        }
    }

    UserCtrl.ascx

    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="UserCtrl.ascx.cs" Inherits="AspNetDynamicControlEvents.UserCtrl" %>
    <asp:Panel ID="pnlControls" runat="server"></asp:Panel>
    <asp:Label ID="lblTest" runat="server" Text=""></asp:Label>

    Default.aspx

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="AspNetDynamicControlEvents.Default" EnableViewState="true" %>
    
    <%@ Register Src="~/UserCtrl.ascx" TagPrefix="uc1" TagName="UserCtrl" %>
    
    
    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <uc1:UserCtrl runat="server" id="UserCtrl" />
        </div>
        </form>
    </body>
    </html>
    

    Default.aspx.cs

    namespace AspNetDynamicControlEvents
    {
        public partial class Default : System.Web.UI.Page
        {
            protected void Page_Load(object sender, EventArgs e)
            {
    
            }
        }
    }

    Web.config

    <?xml version="1.0" encoding="utf-8"?>
    <!--
      For more information on how to configure your ASP.NET application, please visit
      http://go.microsoft.com/fwlink/?LinkId=169433
      -->
    <configuration>
      <system.web>
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5" />
      </system.web>
    </configuration>

    Provavelmente com mais controles dinâmicos seja interessante tratar os ID's também, porém, do jeito que estou fazendo, no momento, funciona sem problemas aqui; recomendo tentar, como falei, do jeito mais simples e ir complementando com o tempo para ver onde o código vai "quebrar" (isso se pelo debug não for possível identificar).



    Att., Rafael Simor

    sexta-feira, 23 de outubro de 2015 18:50
  • Ok SimorC, legal. Eu também costumo testar coisas com o mínimo de código possível, e devo ter falhado em explicar algo... esse controle é TOTALMENTE programado, não existe um arquivo ASCX correspondente. O botão por exemplo, ele deriva do "System.Web.UI.WebControls.Button" e apenas adiciona um propriedade (Behavior) - mesmo se eu trocar por um Button convencional o problema é o mesmo.

    Esse controle vai direto na página ASPX. Assim:

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="CWEB.Web.DefaultPage" EnableViewState="true" %>
    
    <%@ Register TagPrefix="CNT" TagName="CONTROLS" Namespace="CWEB.Info" Assembly="CWEB" %>
    
    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <CNT:Processor runat="server" id="UserCtrl" Labels="Model||Brand" />
        </div>
        </form>
    </body>
    </html>

    sexta-feira, 23 de outubro de 2015 18:56
  • Olá SammuelMiranda,

    tudo bem?

    O problema já foi solucionado?

    Atenciosamente


    Marcos Roberto de Souza Junior

    Esse conteúdo e fornecido sem garantias de qualquer tipo, seja expressa ou implícita

    MSDN Community Support

    Por favor, lembre-se de Marcar como Resposta as respostas que resolveram o seu problema. Essa e uma maneira comum de reconhecer aqueles que o ajudaram e fazer com que seja mais fácil para os outros visitantes encontrarem a resolução mais tarde.

    terça-feira, 27 de outubro de 2015 12:07
  • Não Marcos, estou estudando o que posso fazer, e as dicas dos membros do forum tem sido muito uteis, mas ainda não consegui fazer funcionar.
    terça-feira, 27 de outubro de 2015 15:49
  • Opa, tudo bom SammuelMiranda?

    Vi que vocês já revisaram bastante coisa, e posso estar sendo redundante, mas você já testou acrescentar os eventos de outra forma, por exemplo, acrescentar um método anônimo simples invés do EventHandler pra ver se ocorre o mesmo comportamento, ou então acrescentar o método do EventHandler como um new EventHandler?

        protected MdWeb.Controls.Button CreateButton( string Name, MdWeb.Controls.Button.Behaving Behave )
            {
                MdWeb.Controls.Button nBt = new MdWeb.Controls.Button();
                nBt.ID = Name;
                nBt.CommandName = Name;
                nBt.Behave = Behave;
                nBt.DataBinding += new EventHandler(this.Button_DataBinding);
                return nBt;
            }

    Ou então:

        protected MdWeb.Controls.Button CreateButton( string Name, MdWeb.Controls.Button.Behaving Behave )
            {
                MdWeb.Controls.Button nBt = new MdWeb.Controls.Button();
                nBt.ID = Name;
                nBt.CommandName = Name;
                nBt.Behave = Behave;
                nBt.DataBinding += (s,e) => { MessageBox.Show("Seu evento funcionou!") };
                return nBt;
            }


    Enfim, dá uma olhada nesses exemplos, você tem bastante elemento herdando de outras classes nativas e muita coisa criada de forma dinâmica. Em ambientes onde você tem esse grau de complexidade problemas como este podem aparecer, e geralmente é alguma coisa muito simples que resolve, o problema é identificar no emaranhado do fluxo do programa ^^

    Boa sorte cara, se eu descobrir alguma coisa eu volto a postar nessa thread.

    EDIT: Cara, dá uma olhada na thread dese maluco aqui, acho que o problema era parecido, e a forma como ele resolveu pode te ajudar:

    How to add event handlers to dynamic controls


    • Editado Samuel Pelaquim sexta-feira, 30 de outubro de 2015 18:21 Colei o link direto, esuqeci que é MSDN...
    • Sugerido como Resposta SimorC domingo, 1 de novembro de 2015 22:56
    • Marcado como Resposta Marcos SJ segunda-feira, 2 de novembro de 2015 10:52
    • Não Marcado como Resposta SammuelMiranda terça-feira, 3 de novembro de 2015 10:37
    • Marcado como Resposta SammuelMiranda terça-feira, 3 de novembro de 2015 11:39
    sexta-feira, 30 de outubro de 2015 18:17
  • Oi chara tudo bem?

    Gostei da sua resposta, e me deu uma luz realmente - mas ainda não funcionou. Nem o EDIT com o link que você me passou - notei uma coisa, no método "CreateUI()" eu coloquei:

    private void CreateUI()
    {
        this.Picker = new MdWeb.Controls.PickerSearch();
        if (this.Parent == null || this.Picker.Parent == null) { return; }
        this.Picker.ItemCommand += new SysWCt.RepeaterCommandEventHandler(this.OnItemCommand);
        this.Picker.ID = MdWeb.Pages.Info.Panel<TRec, TTarget>.PickerID;
        this.Picker.EnableViewState = true;
        this.AddNew = new MdWeb.Controls.Button();
        this.AddNew.Click += new Sys.EventHandler(this.OnSave);
        this.AddNew.ID = MdWeb.Pages.Info.Panel<TRec, TTarget>.AddButtonID;
        this.AddNew.Behave = MdWeb.Controls.Button.Behaving.SaveAction;
        this.AddNew.Style.Add("margin-right", "6px");
        this.AddNew.Style.Add("float", "left");
        this.BackButton = new MdWeb.Controls.Button();
        this.BackButton.Click += new Sys.EventHandler(this.OnBack);
        this.BackButton.ID = MdWeb.Pages.Info.Panel<TRec, TTarget>.BackButtonID;
        this.BackButton.Behave = MdWeb.Controls.Button.Behaving.BackAction;
        this.ChildControls = new SysClG.Dictionary<string, MdWeb.Controls.Generic.FieldControl>();
    }

    E no teste da propriedade "Parent" o "this.Parent" responde o "ContentPlaceHolder" onde a classe está, mas o "Parent" do "Picker" (objeto criado) responde NULL. Como "Parent" é ReadOnly, como faço para ele assumir o componente "Panel" (principal) como seu "Parent"?

    terça-feira, 3 de novembro de 2015 10:43
  • Ok, resolvi este problema.

    Depois de Criar cada um dos controles tive que chamar "this.Controls.Add(Control)" para cada um deles. Assim a propriedade "Parent" foi definida e os eventos disparados!!!

    Meu único problema agora é que, este controle implementa a interface "IPostBackDataHandler", mas o método "bool LoadPostData(string postDataKey, global::System.Collections.Specialized.NameValueCollection postCollection)" nunca é chamado - preciso dele para alimentar os dados preenchidos nos "ChildControls" (um dicionário que criei).

    terça-feira, 3 de novembro de 2015 11:16
  • Tudo Resolvido. Bastou colocar "this.Page.RegisterRequiresPostBack(this);" na primeira linha no "OnInit()" e ajustar o método "LoadPostData" para pegar as chaves certas. Tudo correto, graças ao input do chara. Obrigado Samuel.

    public bool LoadPostData(string postDataKey, global::System.Collections.Specialized.NameValueCollection postCollection)
    {
        postDataKey += this.IdSeparator;
        foreach (SysClG.KeyValuePair<string, MdWeb.Controls.Generic.FieldControl> KeyPair in this.ChildControls) { KeyPair.Value.Obj = postCollection[postDataKey + KeyPair.Key]; }
        return true;
    }

    Além disso, no método "CreateControls()" coloquei "this.Controls.Add(Control)" também, ficou assim:

    private void CreateControl<TControl>(TControl Control, string Name, int Pos, bool LabelsMatched) where TControl : SysWeb.UI.Control, MdWeb.Controls.Generic.FieldControl
    {
        Control.ID = Name;
        Control.Label = (LabelsMatched ? this.Labels[Pos] : "Field (" + Pos.ToString() + ")");
        this.ChildControls.Add(Name, Control);
        this.Controls.Add(Control);
    }

    • Marcado como Resposta SammuelMiranda terça-feira, 3 de novembro de 2015 11:39
    terça-feira, 3 de novembro de 2015 11:39