2010-09-26 31 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負責將回發路由到其發起者。

我還在測試它的不良副作用 - 如果任何人有這種想法的經驗,我會很感激一個筆記。