我在一个页面(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;
}
}
}
}
}
我们以类似的方式呈现其他用户控件。我们需要找到一种方法来检测任何这些用户控件上的用户更改(比如更改了文本框或更改了下拉列表等)并处理了父页面。
我不确定代表和活动是否合适,如果是,他们如何适应这种架构是我最大的问题。任何建设性的意见都会有所帮助。
谢谢,
答案 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>