编辑:对于那些来这里有类似问题的人,现在我知道这是一个不好的想法。
喜 我有这样的事情:
bool preventEvents;
protected void Page_Load(object sender, eventargs e)
{
preventEvents = doSomeValidation();
}
protected void Button1_Click(object sender, EventArgs e)
{
if (preventEvents) return;
// ...
}
protected void Repeater1_DataBound(object sender, EventArgs e)
{
if (preventEvents) return;
// ...
}
问题是我在页面上有很多事件。
是否可以在不添加每个方法的“if”行的情况下取消所有其他事件?
编辑:
得到了一些有趣的答案(感谢所有人)但不是我想要的,也许我应该更具体:
给定一些条件,是否可以跳过Page_Load之后的所有事件并跳转到渲染,而无需手动删除/映射每个事件?
答案 0 :(得分:1)
问题是我在页面上有很多事件。
是的,这是一个问题。同一页面中的许多事件都不利于性能(这意味着您要存储大量状态并执行许多http请求)。它们对可维护性不利(你在同一个类中有很多代码都混杂在一起)。它们对可测试性不利(众所周知,asp.net事件难以进行单元测试)。而且它们对可用性不利(不能加书签,不能使用后退按钮,可能导致双重帖子)。
解决方案是使用Post/Redirect/Get pattern。缺点是它将意味着重新思考应用程序设计的一部分,但最终你将拥有一个更好,更快,更易于维护的应用程序。
小心选择跳过事件处理,就像你的计划一样。赔率是您当前的页面状态是多个事件的结果,而不是处理事件可能会破坏页面的预期状态。
答案 1 :(得分:0)
使用自定义验证器,然后它就属于您的标准无效检查。
答案 2 :(得分:0)
您可以使用以下内容,但费用几乎相同
Protected void Page_Load() {
if (preventEvents) {
textbox1.TextChanged -= textbox1_TextChanged;
dropdownlist1.SelectedIndexChanged -= dropdownlist1_SelectedIndexChanged;
// and so on
}
}
答案 3 :(得分:0)
您可以在事件处理程序上创建包装委托,如下所示:
private EventHandler CreateCancelableEventHandler(EventHandler handler)
{
return (sender, e) =>
{
if (!preventEvents)
{
handler.Invoke(sender, e);
}
};
}
此解决方案的缺点是您需要订阅代码隐藏中的所有事件,而不是标记。订阅的用法如下:
button1.OnClick += CreateCancelableEventHandler(Button1_OnClick);
答案 4 :(得分:0)
如何在页面指令中将AutoEventWireup设置为False?即
<%@ Page Language="C#" AutoEventWireup="false" Inherits="MyWebApp.EventWireUpFalse" %>
这样只会发生explicitly "wire-up" in OnInit will be called.事件。这样可以更好地控制页面生命周期中引发的事件。
答案 5 :(得分:0)
你不能“向前跳”到渲染,因为ProcessRequestMain
中没有任何条件允许它。唯一的选择是破解相关控件的事件处理程序。
protected void Page_Load(object sender, EventArgs e) {
// DON'T DO THIS!! Years from now, some poor soul tasked with
// debugging your code will tear their hair out, until they
// discover the unholy magic you have conjured herein. Keep in mind
// this is the 21st century and this person knows where you live.
//
// Seriously, just use the validation built in to ASP.NET.
if ("true".Equals(Request.QueryString["disable_events"], StringComparison.OrdinalIgnoreCase)) {
// disable *all* event handlers on button controls
foreach (var b in this.GetControlDescendants().OfType<Button>()) {
var eventList = (EventHandlerList) typeof (Control)
.GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(b, null);
typeof (EventHandlerList)
.GetField("head", BindingFlags.Instance | BindingFlags.NonPublic)
.SetValue(eventList, null);
}
}
}
完整性的实用程序扩展方法:
/// <summary>
/// Performs a breadth-first traversal of a control's control tree. Unlike
/// FindControl, this method does not descend into controls that have not
/// called EnsureChildControls yet.
/// </summary>
/// <returns>Enumerable of the visited controls.</returns>
public static IEnumerable<Control> GetControlDescendants(this Control parent) {
// Don't force execution of EnsureChildControls
if (!parent.HasControls()) yield break;
foreach (Control child in parent.Controls) {
yield return child;
}
foreach (Control child in parent.Controls) {
foreach (var descendant in child.GetControlDescendants()) {
yield return descendant;
}
}
}
答案 6 :(得分:0)
我遇到了同样的问题。我目前的方法是覆盖RaisePostBackEvent方法并检查&#34; cancelEvents&#34;旗。 RaisePostBackEvent负责将回发路由到其发起者。
我还在测试它是否有不良副作用 - 如果有人对这个想法有经验,我会很感激。