为什么UserControl上的表单没有PostBack



我有一个问题,我无法理解在这个设置中,我失去了捕捉PostBack触发器的能力,或者仅仅是serverclick的处理程序方法,并且放置断点只显示PostBack发生在渲染(Page_Load)时,而不是在单击提交按钮后。请允许我详细说明这个场景,并记住,我改变它的方式的能力有限,必须想办法让它在每个客户端使用ASP.net/C#/WebForms/Bootstrap 4.5进行微小的更改。

Dashboard.aspx[主页]有一个简单的(顶部导航显示徽标和登录用户名,带有注销下拉菜单,侧边栏菜单,单击后将加载到显示区域),显示区域是asp:PlaceHolder元素:

<asp:PlaceHolder runat="server" ClientIDMode="Static" ID="TheScreen">

当加载[主页]时,它会调用API并处理接收到的对象集合,并生成添加一系列UserControlControl1对象(这可以是零项或n项)。让我们调用登录的[默认状态],以便我们稍后可以引用它。

每个Control1(具有唯一的ID)具有3个按钮来执行3个不同的动作。

<a class="btn btn-primary btn-sm" id="action1" runat="server" onserverclick="Command_Click">Do First Action</a>
<a class="btn btn-primary btn-sm" id="action2" runat="server" onserverclick="Command_Click">Do Second Action</a>
<a class="btn btn-primary btn-sm" id="action3" runat="server" onserverclick="Command_Click">Do Third Action</a>

Command_Click只是弹出一个要由Dashboard.aspx处理的事件处理程序

public void Command_Click(object sender, EventArgs e)
{
CommandClicked?.Invoke(sender, e);
}

action1通过一个确认模式进行动态处理,该模式包含一个运行onserverclick并使用API调用重新加载已删除该项的[默认状态]的简单按钮。

<button type="button" class="btn" id="do-action1" runat="server" onserverclick="finish-action1">Do It</button>

这一切都如预期的那样。

action2由[主页]处理,它清除PlaceHolder的控件,然后动态创建并加载另一个UserControl,该UserControl显示该对象的长格式详细信息。

UControl2 theObject = (UControl2)Page.LoadControl("~/path/to/Control2.ascx");
TheScreen.Controls.Clear();
TheScreen.Controls.Add(theObject);

这一切也正如预期的那样。

action3按钮是给我带来问题的按钮,就像action2一样,它在[主页]上处理,在那里它清除PlaceHolder的控件,然后动态创建和加载另一个UserControl,它提供了一个带有一个按钮的简单表单。

UControl3 otherObject = (UControl3)Page.LoadControl("~/path/to/Control3.ascx");
TheScreen.Controls.Clear();
TheScreen.Controls.Add(otherObject);

表单非常简单,包含一个<select>元素,其<option>是使用基于API调用的asp:Repeater填充的,该调用为其提供DataSource。它还有一个简单的<input>文本框字段,最后还有一个提交<button>

<select id="..." name="..." required="required">
<option disabled selected value="">select payment account</option>
<asp:Repeater ID="..." ClientIDMode="Static" runat="server" ItemType="model.namespace">
<ItemTemplate>
<option value="<%#: Eval("...") %>">
<%#: Eval("...") + "  " + Eval("...") %>
</option>
</ItemTemplate>
</asp:Repeater>
</select>
<input id="..." name="..." type="text" required="required" runat="server" />
<button id="finish-action3" class="btn" runat="server" onserverclick="do-action3">Do It</button>

我不明白finish-action3为什么不执行处理程序方法do-action3的操作,它只是刷新回[主页],使用我们从初始状态开始的初始状态,初始Control1正在渲染,没有其他内容,也没有PostBack。

我进行了广泛的搜索,没有发现任何关于这个特定场景的内容,我发现,每个人都在建议使用asp:Button,但这对我的行为没有任何影响。

  1. 如上所述,单击Control3中的finish-action3按钮不会导致基本的HTML5验证,也不会触发do-action3处理程序方法,只需刷新回我们开始的[主页]。

  2. 如果我将do-action3添加到onsubmit属性添加type=submit,我会得到验证,但一旦它通过验证,同样的行为就是加载[主页面]。

  3. 将元素更改为asp:Button完全没有区别。验证是在没有任何特殊情况下触发的(比如使用onsubmit属性或具有type=submit,但一旦验证了相同的行为,就永远不会调用do-action3,甚至不会在control3上触发Page_Load/PostBack,只返回到[主页]

我怀疑我忽略了某个事件,或者没有冒泡,在这个过程中迷路了,但我想不出是什么,在哪里,为什么。为什么屏幕上最后一个由CCD_;提交";单击该按钮不生成PostBack或运行onserverclick处理程序方法,只需刷新到主默认状态页,我在这里缺少什么?

任何帮助都将不胜感激,因为我一直在用头撞墙,试图弄清楚我错过了什么。我从未在MVC或Core中遇到过这种情况,它让我抓狂。

让我们简化一下。基本上,您所说的是以下内容不起作用,因为动态添加的Control3用户控件的btnFinishAction3_Click方法没有启动:

Default.aspx(主页):

<asp:PlaceHolder runat="server" ID="plhPlaceHolder1"></asp:PlaceHolder>
<asp:Button runat="server" ID="btnAction3"
Text="Do Third Action"
OnClick="btnAction3_Click"/>

Default.aspx。cs:

protected void btnAction3_Click(object sender, EventArgs e)
{
AddControl3();
}
private void AddControl3()
{
Control3 objControl3 = (Control3)Page.LoadControl("~/Control3.ascx");
plhPlaceHolder1.Controls.Clear();
plhPlaceHolder1.Controls.Add(objControl3);
}

Control3.ascx:

<asp:Label runat="server" ID="lblMessage"></asp:Label>
<asp:Button runat="server" ID="btnFinishAction3"
Text="Finish Action 3"
OnClick="btnFinishAction3_Click"/>

Control3.ascx.cs:

protected void btnFinishAction3_Click(object sender, EventArgs e)
{
lblMessage.Text = "Finished Action 3.";
}

这是正常行为。在回发之后,动态添加的用户控件不存在;忽略";。在ASP.NET Web窗体中,每次回发后,必须将每个动态控件重新添加到页面中。因此,您需要以下内容:

Default.aspx(主页):

<asp:PlaceHolder runat="server" ID="plhPlaceHolder1"></asp:PlaceHolder>
<asp:HiddenField runat="server" ID="hifControl3Loaded"/>
<asp:Button runat="server" ID="btnAction3"
Text="Do Third Action"
OnClick="btnAction3_Click"/>

Default.aspx。cs:

protected void Page_Load(object sender, EventArgs e)
{            
if (hifControl3Loaded.Value == "1")
{
AddControl3();
}
}
protected void btnAction3_Click(object sender, EventArgs e)
{
AddControl3();
hifControl3Loaded.Value = "1";
}
private void AddControl3()
{
Control3 objControl3 = (Control3)Page.LoadControl("~/Control3.ascx");
plhPlaceHolder1.Controls.Clear();
plhPlaceHolder1.Controls.Add(objControl3);
}

换句话说,一旦用户决定首先单击btnAction3按钮添加Control3,就需要在Page_Load上每次回发时将其添加到主页面。

最新更新