ASP.NET中动态呈现的用户控件的OnChange事件

时间:2015-07-06 23:02:17

标签: c# asp.net

我在一个页面(ABC.aspx)中显示了一组5到6个选项卡中的用户控件。每个用户控件都有许多文本框,Drop Downs等。我需要检测这些用户控件中任何字段的任何用户更改,并在这些用户控件所在的父页面(ABC.aspx)上进行一些处理。 / p>

用户控件实现如下。 每个用户控件都有一个XMl文件,可以读取并相应地创建控件。

ascx.cs中的render方法读取此xml文件并为该用户控件呈现UI Acordingly。

假设用户控件的示例XMl是

 <uigroup groupname ="Schematic(Logical) Symbol Request">
<uirow>
  <uicontrol displayname="Request Type" datatype="DropDown" isrequired="false" domainname="RequestType" dropdownEventHandler="OnScenarioChange(this)" key="Schematic Scenario" defaultValue="New"></uicontrol>
</uirow>
<uirow>
  <uicontrol displayname="Logical Name" datatype="TextBox" isrequired="false" supportedscenarios="New,Use Existing,Update Existing" key="Schematic Symbol Name"></uicontrol>
  <uicontrol displayname="Similar Symbol" datatype="TextBox" isrequired="false" supportedscenarios="New" key="Similar Schematic Symbol"></uicontrol>
</uirow>
<uirow>
  <uicontrol displayname="Type of Change" datatype="DropDown" isrequired="false" domainname="Type of Schematic Change" supportedscenarios="Update Existing" key="Type of Schematic Change"></uicontrol>
  <uicontrol displayname="Layout Preference" datatype="DropDown" isrequired="false" domainname="Schematic Layout Preference" supportedscenarios="New,Update Existing" key="Schematic Layout Preference"></uicontrol>
</uirow>
<uirow>
  <uicontrol displayname="Justification" datatype="DropDown" isrequired="false" domainname="Schematic Justification" supportedscenarios="Update Existing" key="Schematic Justification"></uicontrol>
  <uicontrol displayname="Logical Directory" datatype="DropDown" isrequired="false"   domainname="ICL Logical Directory" supportedscenarios="New" key="ICL Logical Directory"></uicontrol>
</uirow>

Usercontrol.ascx.cs已

protected void Page_Load(object sender, EventArgs e)
    {
    }


    protected void Page_Init(object sender, EventArgs e)
    {
        this.Render();
    }

    public void Render()
    {
        this.Render(this.XmlPath);
    }

我的渲染功能执行以下操作

public void Render(string _filePath)
    {


        UITab tab = this.GetDataFromXML(_filePath);
        foreach (UIGroup g in tab.Groups)
        {
            //Add a panel
            Panel groupPanel = this.AddPanel(g);
            foreach (UIRow r in g.Rows)
            {
                Table table = new Table();
                groupPanel.Controls.Add(table);

                TableRow tableRow = new TableRow();
                table.Rows.Add(tableRow);

                foreach (UIControl c in r.Controls)
                {
                    switch (c.DataType)
                    {
                        case UIDataType.Textbox:
                            this.AddTextBox(groupPanel, c, tableRow);
                            break;
                        case UIDataType.Dropdown:
                            this.AddDropdown(groupPanel, c, tableRow);
                            break;
                        case UIDataType.LabelInfo:
                            this.AddLabelInfo(groupPanel, c,tableRow);
                            break;
                        case UIDataType.Label:
                            this.AddLabel(groupPanel, c,tableRow);
                            break;
                    }
                }
            }
        }
    }

我们以类似的方式呈现其他用户控件。我们需要找到一种方法来检测任何这些用户控件上的用户更改(比如更改了文本框或更改了下拉列表等)并处理了父页面。

我不确定代表和活动是否合适,如果是,他们如何适应这种架构是我最大的问题。任何建设性的意见都会有所帮助。

谢谢,

1 个答案:

答案 0 :(得分:1)

是的,为UserControl创建自定义事件非常有意义。

以下是一个示例(注意:该示例显示了基本概念,并未使用XML文档作为数据源;但是,该示例应该具有足够的指导性,以便您可以将其应用于您所拥有的内容建):

动态注入嵌套控件的简单用户控件的代码:

...在ascx文件中:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="TabControl.ascx.cs" Inherits="StackOverflowAspNetQuestionAnswers.Controls.TabControl" %>
<asp:Panel ID="panel" runat="server">
</asp:Panel>

...在用户控件的代码隐藏文件中:

public partial class TabControl : System.Web.UI.UserControl
    {
        public event EventHandler<ControlChangedEventArgs> ControlUpdated;

        protected void Page_Load(object sender, EventArgs e)
        {
            TextBox textBox = new TextBox();
            textBox.AutoPostBack = true;
            textBox.ID = "textBox";

            textBox.TextChanged += textBox_TextChanged;

            DropDownList dropDown = new DropDownList();
            dropDown.Items.Add(new ListItem("Option 1", "Option 1"));
            dropDown.Items.Add(new ListItem("Option 2", "Option 2"));
            dropDown.AutoPostBack = true;

            dropDown.TextChanged += dropDown_TextChanged;

            panel.Controls.Add(textBox);
            panel.Controls.Add(dropDown);
        }

        void dropDown_TextChanged(object sender, EventArgs e)
        {
            ControlChangedEventArgs args = new ControlChangedEventArgs();

            args.ControlID = ((DropDownList)sender).ID;
            args.ControlValue = ((DropDownList)sender).SelectedValue;

            ControlUpdated(this, args);

            //CODE EDIT:
            UnhookEventHandlers();

        }

        void textBox_TextChanged(object sender, EventArgs e)
        {
            ControlChangedEventArgs args = new ControlChangedEventArgs();
            args.ControlID = ((TextBox)sender).ID;
            args.ControlValue = ((TextBox)sender).Text;
            ControlUpdated(this, args);

            //CODE EDIT:
            UnhookEventHandlers();

        }

        public virtual void OnControlUpdated(ControlChangedEventArgs e)
        {
            EventHandler<ControlChangedEventArgs> handler = ControlUpdated;
            if (handler != null)
            {
                handler(this, e);
            }

            //CODE EDIT:
            UnhookEventHandlers();

        }

        //CODE EDIT:
        private void UnhookEventHandlers()
        {
            foreach (var c in panel.Controls.OfType<DropDownList>())
            {
                c.TextChanged -= dropDown_TextChanged;
            }

            foreach (var c in panel.Controls.OfType<TextBox>())
            {
                c.TextChanged -= textBox_TextChanged;
            }
        }

    }

    public class ControlChangedEventArgs : EventArgs
    {
        public string ControlID { get; set; }
        public string ControlValue { get; set; }  
    }

以下是使用此简单制表符控件的父页面的代码:

...在.aspx文件中:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="RaisingEventFromUserControl_Question.aspx.cs" Inherits="StackOverflowAspNetQuestionAnswers.RaisingEventFromUserControl_Question" %>

<%@ Register Src="~/Controls/TabControl.ascx" TagPrefix="uc1" TagName="TabControl" %>


    <!DOCTYPE html>

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <asp:Label ID="message" runat="server" />
            <uc1:TabControl runat="server" id="TabControl" />
        </div>
        </form>
    </body>
    </html>

...在父页面的代码隐藏文件中:

 public partial class RaisingEventFromUserControl_Question : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            TabControl.ControlUpdated += TabControl_ControlUpdated;
        }

        void TabControl_ControlUpdated(object sender, ControlChangedEventArgs e)
        {
           //EDIT: add code to update some data source to lock the form from other users
            message.Text = String.Format("A child control with an ID of '{0}' was updated. It now has the value of '{1}'.", e.ControlID, e.ControlValue);
        }
    }

正如您在示例中所看到的,我有一个名为&#34; ControlUpdated,&#34;的自定义事件。当我在运行时动态注入到UserControl中的嵌套TextBox或DropDownList发生更改时,我会触发它。另外,请记住我设置了&#34; AutoPostBack&#34; TextBox和DropDownList的属性,以确保每当我更改文本框/下拉列表的值时,ASP.Net生成的客户端代码都会执行。

此外,您可以看到,对于我的自定义事件,我还创建了一个自定义EventArgs类,以便我可以传递更新的嵌套控件中的相关信息(即ID和更改的值)。 / p>