2010-09-26 72 views
0

编辑:对于那些谁到这里来有类似的问题,现在我知道这是一个坏主意。取消所有事件从Page_Load中

喜, 我有这样的事情:

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; 
    // ... 
} 

的问题是,我在页面上的事件不少。

是否有可能只是取消所有其他事件无添加“如果”行上的每一个方法?


编辑:

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

给予一定的条件

,是有可能跳过Page_Load之后的所有事件并跳转到渲染,而无需手动移除/映射每个事件?

回答

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; 
     } 
    } 
} 
+0

不错的一个,我会给它一个尝试 (仅用于学术目的,我现在明白了我即将释放的恶魔) – y34h 2010-09-27 03:50:28

0

使用自定义的验证,然后它只是属于你的标准作废的支票。

+0

thx,但这样我就必须把if(Page.IsValid)正确?...所以几乎是相同的问题=/ – y34h 2010-09-26 18:41:08

+0

@ y34h - 为什么你不检查IsValid?你没有任何验证器,并且从未打算有任何验证器吗?一个简单的正则表达式应该可以做到这一点 - 但是如果你的页面上有这么多事件,那么在过去的6个小时内你还没有添加代码......好吧,我为你感觉到了。 ;) – 2010-09-27 00:17:55

+0

代码是在我的办公室,我在家里^^ ...无论如何,该项目结束前几天,我只是寻找更好的方法来做下一次 – y34h 2010-09-27 01:59:09

0

您可以使用以下,但是这将是几乎同样的成本

Protected void Page_Load() { 
    if (preventEvents) { 
     textbox1.TextChanged -= textbox1_TextChanged; 
     dropdownlist1.SelectedIndexChanged -= dropdownlist1_SelectedIndexChanged; 
     // and so on 
    } 
} 
0

您可以在事件处理程序创建包装的委托,像这样:

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

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

button1.OnClick += CreateCancelableEventHandler(Button1_OnClick); 
0

如何在您的页面指令中将AutoEventWireup设置为False?即。只有

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

这样的事件,你explicitly "wire-up" in OnInit will be called.这会给你的页面生命周期都提出了哪些事件更能控制。

1

的问题是,我在页面上的事件不少。

是的,这是一个问题。同一页面中的许多事件对性能不利(这意味着您正在存储大量状态并执行很多http请求)。它们对可维护性不利(你在同一个类中有很多代码都混杂在一起)。它们对可测试性不利(asp.net事件对于单元测试来说非常困难)。而且它们对可用性不利(不能书签,不能使用后退按钮,可能导致双重帖子)。

解决方法是使用Post/Redirect/Get pattern。缺点是这意味着您的应用程序设计需要重新考虑部分内容,但最终您将拥有一款更好,更快速且易于维护的应用程序。

请谨慎选择跳过事件处理,就像您的计划一样。赔率是你目前的页面状态是几个事件的结果,而不是处理事件可以打破你的页面的预期状态。

+0

好吧,这是真的,我实际上对我在那里编码的内容感到羞愧,但是要重构它,以致迟到 – y34h 2010-09-27 03:45:04

+0

+ 1'重新设计陪审团操纵一周中的任何一天。 – 2010-09-27 20:44:16

0

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

我还在测试它的不良副作用 - 如果任何人有这种想法的经验,我会很感激一个笔记。