代码之家  ›  专栏  ›  技术社区  ›  y34h

取消页面加载中的所有事件

  •  0
  • y34h  · 技术社区  · 14 年前

    编辑:对于那些来这里遇到类似问题的人来说,现在我知道这是个坏主意。

    你好, 我有这样的想法:

    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”行?


    得到了一些有趣的答案(感谢大家),但不是我想要的,也许我应该更具体一些:

    7 回复  |  直到 14 年前
        1
  •  0
  •   Michael Kropat    14 年前

    不能“跳转”到渲染,因为渲染中没有任何条件 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;
            }
        }
    }
    
        2
  •  1
  •   Joel Coehoorn    14 年前

    是的,那是个问题。同一页中的许多事件对性能不利(这意味着您要存储大量状态并执行许多http请求)。它们不利于可维护性(您在同一个类中有很多代码都是杂乱无章的)。它们不利于可测试性(asp.net众所周知,事件很难进行单元测试。而且它们不利于可用性(不能添加书签,不能使用back按钮,可能会导致双贴)。

    解决方法是使用 Post/Redirect/Get pattern . 不利的一面是,这将意味着重新考虑你的应用程序设计的一部分,但最终你会有一个应用程序,只是工作得更好,更快,更容易维护。

    小心选择跳过事件处理,就像你的计划一样。您当前的页面状态很可能是多个事件的结果,不处理事件可能会破坏页面的预期状态。

        3
  •  0
  •   sh_kamalh    14 年前

    Protected void Page_Load() {
       if (preventEvents) {
          textbox1.TextChanged -= textbox1_TextChanged;
          dropdownlist1.SelectedIndexChanged -= dropdownlist1_SelectedIndexChanged;
          // and so on
       }
    }
    
        4
  •  0
  •   Andrew Bezzub    14 年前

    您可以在事件处理程序上创建包装委托,如下所示:

        private EventHandler CreateCancelableEventHandler(EventHandler handler)
        {
            return (sender, e) =>
                       {
                            if (!preventEvents)
                            {
                                handler.Invoke(sender, e);
                            }
                       };
        }
    

    此解决方案的缺点是,您需要以代码隐藏方式订阅所有事件,而不是在标记中订阅。订阅的用法如下:

    button1.OnClick += CreateCancelableEventHandler(Button1_OnClick);
    
        5
  •  0
  •   Dan Diplo    14 年前

    在页面指令中将AutoEventWireup设置为False如何?例如。

    <%@ Page Language="C#" AutoEventWireup="false" Inherits="MyWebApp.EventWireUpFalse" %>
    

    那样只会让你 explicitly "wire-up" in OnInit will be called.

        6
  •  0
  •   Mark Brackett    14 年前

    使用自定义验证器,然后它就落入了您的标准无效检查。

        7
  •  0
  •   Rolf    10 年前

    我也有同样的问题。我当前的方法是覆盖RaisePostBackEvent方法并检查“cancelEvents”标志。RaisePostBackEvent负责将回发路由到其发起方。