取消Page_Load中的所有事件

时间:2010-09-26 18:00:10

标签: c# asp.net events

编辑:对于那些来这里有类似问题的人,现在我知道这是一个不好的想法。

喜 我有这样的事情:

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之后的所有事件并跳转到渲染,而无需手动删除/映射每个事件?

7 个答案:

答案 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负责将回发路由到其发起者。

我还在测试它是否有不良副作用 - 如果有人对这个想法有经验,我会很感激。