2010-09-26 5 views
0

EDIT: для тех, кто приезжает сюда с аналогичной проблемой, теперь я знаю, что это была НЕОБХОДИМАЯ ИДЕЯ.Отменить все события из 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; 
    // ... 
} 

Проблема заключается в том, что у меня есть много событий на этой странице.

Можно ли просто отменить все дальнейшие события без добавления строки «if» для каждого метода?


EDIT:

получил некоторые интересные ответы (спасибо всем), но не то, что я искал, может быть, я должен быть более конкретным:

дано какое-либо условие, является возможно ли пропустить все события после 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); 
     } 
    } 
} 

Utility метод расширения для полноты:

/// <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

0

Используйте специальный валидатор, а затем он просто попадает в стандартную недействительную проверку.

+0

thx, но в этом случае мне нужно было бы поставить if (Page.IsValid) правильно? ... так почти такая же проблема =/ – y34h

+0

@ y34h - Почему вы не проверяете IsValid в любом случае? У вас нет валидаторов, и вы никогда не планируете их иметь? Простое регулярное выражение должно делать трюк, но если на вашей странице так много событий, что вы не добавили код за последние 6 часов ... ну, я чувствую к вам. ;) –

+0

код в моем офисе, и я дома ^^ ... в любом случае, этот проект закончился несколько дней назад, я просто искал лучшие способы сделать это в следующий раз – y34h

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 Ложь в вашей директиве страницы? то есть. только

<%@ 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

+0

+ 1'. редизайн над фальсификацией присяжных в любой день недели. –

0

У меня такая же проблема. Мой текущий подход заключается в том, чтобы перезаписать метод RaisePostBackEvent и проверить флаг «cancelEvents». RaisePostBackEvent отвечает за маршрутизацию обратной передачи отправителю.

Я все еще проверяю его на плохие побочные эффекты - я был бы признателен за заметку, если кто-нибудь испытает эту идею.

Смежные вопросы