ASP自定义控件不会触发正确的事件

时间:2010-06-30 15:14:23

标签: asp.net

我正在构建一个自定义控件库。我的控件继承自CompositeControl。 根据用户的答案,我必须插入更多的自定义控件。我从客户端代码传入了PlaceHolder(_ph)。我将控件插入PlaceHolder。

我的问题是我在事件处理程序中插入的控件不会触发其事件,但会触发父事件。例如,如果我有一个EddDropDown A,并且用户选择了答案,我必须在edd_SelectedIndexChanged中创建EddDropDown B和C.当我为B选择答案时,它会为A而不是B触发SelectedIndexChanged。

我认为这与进入页面周期迟到有关。我不知道如何解决它。请帮忙。非常感谢任何助理。 提前谢谢。

这是我的控件的一个示例:

using System;

使用System.Collections.Generic; 使用System.Collections;

使用System.Linq; 使用System.Text; 使用System.ComponentModel; 使用System.Security.Permissions; 使用System.Web; 使用System.Web.UI; 使用System.Web.UI.WebControls; 使用CommerceBank.DueDiligence.ServiceProxies.Internal.Edd; 使用System.Collections.Specialized; 使用System.Runtime.Serialization;

命名空间CommerceBank.DueDiligence.ClientFacade.WebForms {     public class EddDropDownListArgs:EventArgs     {         private int _iQuestionID;         string _sAnswer = string.Empty;         private DueDiligenceProfile _customerProfile;

    public EddDropDownListArgs(int iQuestionID, string sAnswer,DueDiligenceProfile customer)
    {
        _iQuestionID = iQuestionID;
        _sAnswer = sAnswer;
        _customerProfile = customer;
    }
    public int QuestionID
    {
        get
        {
            return _iQuestionID;
        }
        set
        {
            _iQuestionID = value;
        }
    }
    public string Answer
    {
        get
        {
            return _sAnswer;
        }
        set
        {
            _sAnswer = value;
        }
    }
    public DueDiligenceProfile customerProfile
    {
        get
        {
            return _customerProfile;
        }
        set
        {
            _customerProfile = value;
        }
    }

}
public delegate void EddDropDownSelectedIndexChangedHandler(object sender, EddDropDownListArgs ce);



[
AspNetHostingPermission(SecurityAction.Demand,
    Level = AspNetHostingPermissionLevel.Minimal),
AspNetHostingPermission(SecurityAction.InheritanceDemand,
    Level = AspNetHostingPermissionLevel.Minimal),
DefaultProperty("ID"),
ToolboxData("<{0}:EddDropDown runat=\"server\"> </{0}:EddDropDown>"),
Serializable
]
public class EddDropDown : CompositeControl, IChannelControl,ISerializable, IPostBackEventHandler, IPostBackDataHandler
{
    [Serializable]
    struct EddDropDownData
    {
        public int _iQuestionID;
        public String _sQuestion;
        //public AnswerOption[] _PossibleAnswers;
        public String _sAnswer;
        //public DueDiligenceProfile _customerProfile;
    }

    [
    Bindable(true),
    Category("Appearance"),
    DefaultValue(""),
    Description("This is EddCheckBox"),
    Localizable(true)
    ]
    private int _iQuestionID=-1;
    private String _sQuestion = string.Empty;
    private AnswerOption[] _PossibleAnswers;
    private String _sAnswer = string.Empty;
    private DueDiligenceProfile _customerProfile;
    private EddDropDownData _data = new EddDropDownData();
    Label _lQuestion = null;
    DropDownList _ddl = null;

    #region implement custom events
    public event EddDropDownSelectedIndexChangedHandler SelectedIndexChanged;
    protected virtual void OnSelectedIndexChanged(EddDropDownListArgs eddEvent)
    {
        if (SelectedIndexChanged != null)
        {
            System.Diagnostics.Trace.WriteLine("OnSelectedIndexChanged. QuestionID:"
                + eddEvent.QuestionID
                + " Answer: "
                + eddEvent.Answer);
            SelectedIndexChanged(this, eddEvent);
        }
    }
    #endregion

    #region IPostBackEventHandler_implementation
    // Define the method of IPostBackEventHandler that raises change events.
    void IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
    {
        System.Diagnostics.Trace.WriteLine("in RaisePostBackEvent" + eventArgument);
        OnSelectedIndexChanged(new EddDropDownListArgs(EDDQuestionID(), EDDAnswerValue(), _customerProfile));
    }
    #endregion

    #region IPostBackDataHandler_implementation
    bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection)
    {
        //System.Diagnostics.Trace.WriteLine("in LoadPostData");

        //int i = int.Parse(postCollection["SelectedIndex"]);
        //string s = postCollection["SelectedValue"];

        //if (SelectedIndex >= 0)
        //    Page.RegisterRequiresRaiseEvent(this);
        //return false;
        return true;
    }
    void IPostBackDataHandler.RaisePostDataChangedEvent()
    {
        System.Diagnostics.Trace.WriteLine("in RaisePostDataChangedEvent");
    }
    #endregion

    #region ISerializable_implementation
    [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("ControlType", GetType().Name);
        info.AddValue("ControlID", ID);
        info.AddValue("QuestionID", _iQuestionID);
        info.AddValue("Question", Question);
        info.AddValue("Answer", EDDAnswerValue());
        info.AddValue("PossibleAnswerCount", _PossibleAnswers.Length);
        for (int i=0; i < _PossibleAnswers.Length; i++)
        {
            info.AddValue("a" + i.ToString(), _PossibleAnswers[i]);
        }
    }
    #endregion


    #region IChannel_implementation
    public int EDDQuestionID()
    {
        return QuestionID;
    }
    public string EDDAnswerValue()
    {
        EnsureChildControls();
        for (int i = 0; i < Controls.Count; i++)
        {
            if (Controls[i].ID == "ans" + QuestionID)
            {
                _sAnswer = ((DropDownList)Controls[i]).SelectedValue;
                _data._sAnswer = ((DropDownList)Controls[i]).SelectedValue;
                ViewState["SelectedIndex"] = ((DropDownList)Controls[i]).SelectedIndex;

                return ((DropDownList)Controls[i]).SelectedValue;
            }
        }
        return null;
    }
    #endregion

    #region Overriden properties
    public override ControlCollection Controls
    {
        get
        {
            EnsureChildControls();
            return base.Controls;
        }
    }
    #endregion

    #region Properties
    public int QuestionID
    {
        get
        {
            _iQuestionID = (int)ViewState["QuestionID"];
            return _iQuestionID;
        }
        set
        {
            ViewState["QuestionID"] = value;
            _iQuestionID = value;
        }
    }
    public string Question
    {
        get
        {
            _sQuestion = (string)ViewState["Question"];
            return _sQuestion;
        }
        set
        {
            ViewState["Question"] = value;
            _sQuestion = value;
        }
    }
    public string Answer
    {
        get
        {
            return _sAnswer;
        }
        set
        {
            _sAnswer = value;
        }
    }
    public int SelectedIndex
    {
        get {
            EnsureChildControls();
            if (ViewState["SelectedIndex"] != null)
                _ddl.SelectedIndex = (int)ViewState["SelectedIndex"];
            else
                _ddl.SelectedIndex = 0;
            return _ddl.SelectedIndex;
        }
        set {
            EnsureChildControls();
            ViewState["SelectedIndex"] = value;
            _ddl.SelectedIndex = value;
        }
    }
    public string SelectedValue
    {
        get
        {
            EnsureChildControls();
            _ddl.SelectedValue =(string)ViewState["SelectedValue"];
            return _ddl.SelectedValue;
        }
        set 
        {
            EnsureChildControls();
            ViewState["SelectedValue"] = value;
            _ddl.SelectedValue = value;
        }
    }
    #endregion


    public EddDropDown(int iQuestionID
        , string sQuestion
        , DueDiligenceProfile cust
        , AnswerOption[] sPossibleAnswers
        )
    {
        System.Diagnostics.Trace.WriteLine("Add EddDropDown.  QuestionID :" 
                                            + iQuestionID.ToString() 
                                            + sQuestion);
        QuestionID = iQuestionID;
        Question = sQuestion;

        _data._iQuestionID = iQuestionID;
        _data._sQuestion = sQuestion;

        _PossibleAnswers = sPossibleAnswers;
        _customerProfile = cust;
        ID = iQuestionID.ToString()+GetCustomerID();


    }

    public EddDropDown(SerializationInfo info, StreamingContext context)
    {
        string sControlType = info.GetString("ControlType");
        ID = info.GetString("ControlID");
        QuestionID = info.GetInt32("QuestionID");
        Question = info.GetString("Question");
        string sAnswer = info.GetString("Answer");

        int iAnswerCount = info.GetInt32("PossibleAnswerCount");
        List<AnswerOption> answerOptions = new List<AnswerOption>();
        for (int i = 0; i < iAnswerCount; i++)
        {
            Type t = typeof(AnswerOption);
            AnswerOption ao = (AnswerOption)info.GetValue("a" + i.ToString(), t);
            answerOptions.Add(ao);
        }

        _PossibleAnswers = answerOptions.ToArray();
    }
    protected override object SaveViewState()
    {
        ViewState["SelectedIndex"] = _ddl.SelectedIndex;

        return base.SaveViewState();
    }

    protected override void LoadViewState(object savedState)
    {
        //if (ViewState["SelectedIndex"] != null)
        //    _ddl.SelectedIndex = (int)ViewState["SelectedIndex"];
        //else
        //    _ddl.SelectedIndex = 0;
        if (savedState != null)
        {
            Pair mystate = (Pair)savedState;
            ArrayList al =(ArrayList)mystate.First;
            for (int i = 0; i < al.Count;i++ )
            {
                if (al[i].GetType().Name == "IndexedString")
                {
                    if (((IndexedString)al[i]).Value == "SelectedIndex")
                    {
                        ViewState["SelectedIndex"] = al[i + 1].ToString();
                        System.Diagnostics.Trace.WriteLine(al[i + 1].ToString());
                    }
                }
            }



        }
        base.LoadViewState(savedState);
    }
    //need this to get the post back
    protected override void AddAttributesToRender(HtmlTextWriter writer)
    {
        writer.AddAttribute(HtmlTextWriterAttribute.Name, this.ID);
        writer.AddAttribute(HtmlTextWriterAttribute.Onchange,
            Page.ClientScript.GetPostBackEventReference(this, ID));
        //writer.AddAttribute(HtmlTextWriterAttribute.Onchange,
        //    Page.ClientScript.GetPostBackEventReference(_ddl, _ddl.ID));
        base.AddAttributesToRender(writer);
    }

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);
        Page.RegisterRequiresPostBack(this);//must register postback in OnPreRender
    }
    protected override void Render(HtmlTextWriter writer)
    {
        //Ensures that this control is nested in a server form
        if (Page != null)
        {
            Page.VerifyRenderingInServerForm(this);
        }
        base.Render(writer);
    }
    protected override void RenderContents(HtmlTextWriter writer)
    {
        RenderChildren(writer);
    }

    protected override void CreateChildControls()
    {
        Controls.Clear();

        _lQuestion = new Label();
        _lQuestion.ID = "quest" + QuestionID;
        _lQuestion.Text = Question;
        _ddl = new DropDownList();
        _ddl.ID = "ans" + QuestionID;

        //add "select one"
        ListItem liSelectOne = new ListItem("Please select one");
        _ddl.Items.Add(liSelectOne);
        for (int i = 0; i < _PossibleAnswers.Count(); i++)
        {
            AnswerOption a = _PossibleAnswers[i];

            ListItem li = new ListItem(a.Value.ToString());
            _ddl.Items.Add(li);
            //if (a.ChildQuestions == null)//default it to the answer that don't have some children
            //    ddl.Items[i].Selected = true;
        }
        if (_sAnswer != string.Empty)
            _ddl.SelectedValue = _sAnswer;


        _ddl.AutoPostBack = true;//must have
        _ddl.SelectedIndexChanged += new EventHandler(ddl_SelectedIndexChanged);
        if (ViewState["SelectedIndex"] != null)
            _ddl.SelectedIndex = (int)ViewState["SelectedIndex"];
        //else
        //    _ddl.SelectedIndex = 0;

        Page.RegisterRequiresPostBack(_ddl);
        Page.RegisterRequiresControlState(_ddl);

        Controls.Add(new LiteralControl("<br>"));
        Controls.Add(_lQuestion);
        Controls.Add(new LiteralControl("<br>"));
        Controls.Add(_ddl);

        ChildControlsCreated = true;
        //ClearChildViewState();
    }
    private string GetCustomerID()
    {
        if (_customerProfile.Customer.PermanentId >0)
            return _customerProfile.Customer.PermanentId.ToString();
        else if (_customerProfile.Customer.RcifId != null && _customerProfile.Customer.RcifId != "")
            return _customerProfile.Customer.RcifId;
        else
            return _customerProfile.Customer.TaxId.ToString();
    }
    //to do: delete
    //void edd_SelectedIndexChanged(object sender, EddDropDownListArgs ea)
    //{
    //    System.Diagnostics.Trace.WriteLine("get here");
    //}
    void ddl_SelectedIndexChanged(object sender, EventArgs e)
    {
        Control c = (Control)sender;
        System.Diagnostics.Trace.WriteLine("ddl_SelectedIndexChanged " 
            + c.GetType().Name);
        OnSelectedIndexChanged(new EddDropDownListArgs(EDDQuestionID(), EDDAnswerValue(),_customerProfile));
    }
    protected override void RenderChildren(HtmlTextWriter output)
    {
        if (HasControls())
        {
            for (int i = 0; i < Controls.Count; i++)
            {
                Controls[i].RenderControl(output);
            }
        }

    }



}

}

这是创建控件的代码:

        public EddDropDown GetDropDown(DueDiligenceProfile cust, Question quest)
    {

        Control c = null;
        if (HasControl(quest.Id.ToString(), "EddDropDown", ref c))
            return (EddDropDown)c;
        string sQuestion = null;

        AnswerOption[] sPossAnswers;
        sPossAnswers = FindPossibleAnswers(cust.Questions, quest.Id, ref sQuestion);
        if (sPossAnswers == null)
            throw (new Exception("failed to get possible answers"));
        EddDropDown edd = new EddDropDown(quest.Id,
                            sQuestion,
                            cust,
                            sPossAnswers
                            );
        edd.ID = quest.Id.ToString();
        edd.SelectedIndexChanged += new EddDropDownSelectedIndexChangedHandler(edd_SelectedIndexChanged);
        _data._EDDControls.Add(edd);
        int iParentQuestionID = FindParentQuestionID(cust.Questions, quest.Id, ref sQuestion);
        int iControlIdx = GetIndexOf(iParentQuestionID, _ph.Controls);
        if (iControlIdx >-1)
            _ph.Controls.AddAt(iControlIdx + 1, edd);
        else
            _ph.Controls.Add(edd);
        //build children questions if they have result
        if (quest.Results.Length >0)
        {

            foreach (Result r in quest.Results)
            {
                edd.SelectedValue = r.Value;
                foreach (AnswerOption ao in quest.AnswerOptions)
                {
                    if (r.Value == ao.Value)
                    {
                        if (ao.ChildQuestions == null)
                            continue;
                        foreach (Question q in ao.ChildQuestions)
                        {
                            EddDropDown e = GetDropDown(cust, q);
                            e.BackColor = System.Drawing.Color.CadetBlue;
                        }
                    }
                }
            }
        }
        return edd;

    }
    void edd_SelectedIndexChanged(object sender, EddDropDownListArgs ea)
    {
        System.Diagnostics.Trace.WriteLine("EddQuestionare--edd_SelectedIndexChanged. QuestionID:"
                    + ea.QuestionID
                    + " Answer: "
                    + ea.Answer);

        //Control parentControl = null;
        //if (sender.GetType().Name == "EddDropDown")
        //{
        //    parentControl = (Control)sender;

        //}
        //Control c = (Control)sender;

        //while (c.GetType().Name != "PlaceHolder")
        //    c = c.Parent;

        string sQuestion = null;

        AnswerOption[] ansOptions = FindPossibleAnswers(ea.customerProfile.Questions
                                , ea.QuestionID
                                , ref sQuestion);

        foreach (AnswerOption ao in ansOptions)
        {
            if (ao.Value == ea.Answer)//found answer
            {
                if (ao.ChildQuestions == null)
                    break;

                //create sub questions
                for (int i = 0; i < ao.ChildQuestions.Length; i++)//and there are subquestions
                {
                    _ph.Controls.Add(new LiteralControl("&nbsp;&nbsp;&nbsp;&nbsp;"));
                    if (ao.ChildQuestions[i].AnswerOptions.Length > 2)
                    {
                        EddDropDown subQues = GetDropDown(ea.customerProfile
                                            , ao.ChildQuestions[i]);
                        subQues.BackColor = System.Drawing.Color.Aqua;
                    }
                    else if (ao.ChildQuestions[i].AnswerOptions.Length == 2)
                    {
                        EddRadioButtonList erb = GetRadioButtonList(ea.customerProfile
                                            , ao.ChildQuestions[i].Id);
                        erb.BackColor = System.Drawing.Color.BlueViolet;
                    }
                    else
                    { 
                        EddTextArea eta = GetTextArea(ea.customerProfile
                                            , ao.ChildQuestions[i].Id);
                        eta.BackColor = System.Drawing.Color.Bisque;
                    }
                }
                break;
            }
        }
        //DisplayControls();
        //Serialize();
    }

有些事情我没有清理过,但你明白了。

1 个答案:

答案 0 :(得分:0)

回发事件可能无法进入您的控制范围。

在使用您的控件的页面中,尝试重写RaisePostbackEvent并为每个控件调用RaisePostBackEvents:

protected override void RaisePostBackEvent(IPostBackEventHandler sourceControl, string eventArgument)
{

    this.yourcustomcontrol1.RaisePostBackEvent(sourceControl, eventArgument);
    this.yourcustomcontrol2.RaisePostBackEvent(sourceControl, eventArgument);

    base.RaisePostBackEvent(sourceControl, eventArgument);
}