Отменить все события из Page_Load - PullRequest
0 голосов
/ 26 сентября 2010

РЕДАКТИРОВАТЬ: для тех, кто приходит сюда с подобной проблемой, теперь я знаю, что это была ПЛОХАЯ ИДЕЯ.

привет, У меня есть что-то вроде этого:

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 ]

1 голос
/ 27 сентября 2010

Проблема в том, что у меня МНОГО событий на странице.

Да, это проблема. Многие события на одной странице плохо влияют на производительность (это означает, что вы сохраняете много состояний и выполняете много http-запросов). Они плохо подходят для сопровождения (у вас много кода в одном классе, который все перемешано). Они плохо подходят для тестируемости (события asp.net общеизвестно сложны для модульного тестирования). И они плохо подходят для удобства использования (не могут создавать закладки, не работают с кнопкой «назад», могут привести к двойным публикациям).

Решение - использовать шаблон Post / Redirect / Get . Недостатком является то, что это будет означать переосмысление частей вашего приложения, но в итоге у вас будет приложение, которое работает лучше, быстрее и проще в обслуживании.

Будьте внимательны, выбирая просто пропустить обработку событий, как и ваш план. Вероятность того, что ваше текущее состояние страницы является результатом нескольких событий, и отсутствие обработки событий может нарушить ожидаемое состояние вашей страницы.

0 голосов
/ 27 апреля 2015

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

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

0 голосов
/ 27 сентября 2010

Вы не можете «прыгнуть вперед» к рендерингу, потому что в 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 голосов
/ 26 сентября 2010

Как насчет установки AutoEventWireup в False в вашей директиве страницы?то есть.

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

Таким образом будут вызываться только те события, которые вы явно "подключаете" в OnInit. Это даст вам гораздо больший контроль над событиями, возникающими в жизни страницы.-цикл.

0 голосов
/ 26 сентября 2010

Вы можете создать делегат переноса через обработчик событий, примерно так:

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

Недостатком этого решения является то, что вам нужно будет подписаться на все события в коде, а не в разметке. Использование подписки будет выглядеть так:

button1.OnClick += CreateCancelableEventHandler(Button1_OnClick);
0 голосов
/ 26 сентября 2010

Вы можете использовать следующее, но это будет почти такая же стоимость

Protected void Page_Load() {
   if (preventEvents) {
      textbox1.TextChanged -= textbox1_TextChanged;
      dropdownlist1.SelectedIndexChanged -= dropdownlist1_SelectedIndexChanged;
      // and so on
   }
}
0 голосов
/ 26 сентября 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...