Как я могу предотвратить запуск события в C #? - PullRequest
5 голосов
/ 16 февраля 2011

У меня есть древовидная структура с флажками, и у меня есть следующий обработчик для события "AfterCheck":

private void trvAvailableFiles_AfterCheck(object sender, TreeViewEventArgs e)
{
    if (!_isCheckingInProgress)
    {
        trvAvailableFiles.BeginUpdate();

        var nodePath = e.Node.Tag.ToString();
        bool isChecked = e.Node.Checked;
        e.Node.Nodes.Clear();

        try
        {
            _fileTreeLogic.GetChildNodes(e.Node, true);
            e.Node.ExpandAll();

            _isCheckingInProgress = true;
            SetChildrenCheckState(e.Node, isChecked);
            _isCheckingInProgress = false;

        }
        finally
        {
            trvAvailableFiles.EndUpdate();
        }
    }
}

Если вы посмотрите внимательно, вы увидите, что я проверяю, "_isCheckingInProgress". Если это не так, тогда я продолжаю и расширяю все узлы и вызываю метод SetChildrenCheckState (). Проблема, с которой я столкнулся, заключается в том, что SetChildrenCheckState () впоследствии заставит каждый дочерний узел запускать событие AfterCheck для своего собственного узла.

У меня вопрос: есть ли более чистый способ разрешить запуск первого события AfterCheck, но не последующие? Мне кажется, что мне нужно иметь переменную экземпляра bool для проверки и установки.

Ответы [ 4 ]

6 голосов
/ 16 февраля 2011

Использование: if(e.Action != TreeViewAction.Unknown) вместо if (!_isCheckingInProgress). См TreeViewAction.

Когда пользователь использует клавиатуру или мышь для проверки флажков, e.Action будет TreeViewAction.ByKeyboard или TreeViewAction.ByMouse.

MSDN предоставляет это в качестве примера кода для TreeView.AfterCheck Event .

Редактировать 1: Очевидно, что если вы сами устанавливаете флажок в коде, переместите код в обработчике событий в новую функцию, и у кода, который устанавливает флажок, вызовите его напрямую. Смысл этого решения состоит в том, чтобы позволить вам использовать обработчики событий для пользовательского ввода, не вызывая эти события, когда вы сами устанавливаете флажки с помощью кода.

Правка 2: См. Ответ Спенсера для объяснения моего комментария в Правке 1

4 голосов
/ 16 февраля 2011

Одна рекомендация, которую вы иногда будете видеть в SO, - не помещать много кода в сами обработчики событий. Есть ряд причин для этого. Во-первых, в вашем случае было бы легче понять вызов как:

private void trvAvailableFiles_AfterCheck(object sender, TreeViewEventArgs e)
{
    if (!_isCheckingInProgress) 
    {
        _isCheckingInProgress = true;
        try { GetAvailableFiles(); } catch {}
        _isCheckingInProgress = false;
    }
}

И поместить оставшуюся часть кода в GetAvailableFiles(). Это создает разделение между кодом события и кодом действия, с которым согласится большинство людей. Это стоит сделать различие.

Во-вторых, что может или не может быть применимо в вашем случае, это то, что несколько событий могут вызвать одно и то же действие. Например, mnuFileQuit_Click и btnClose_Click в качестве очевидного примера. Если оба делают вызовы на CloseApplication(), это удаляет много избыточного кода.

2 голосов
/ 16 февраля 2011

Лично я использую функцию, которая удаляет, а затем добавляет событие.

private void trvAvailableFiles_AfterCheck(object sender, TreeViewEventArgs e)
{
    EnableEvents(false);
    trvAvailableFiles.BeginUpdate();

    var nodePath = e.Node.Tag.ToString();
    bool isChecked = e.Node.Checked;
    e.Node.Nodes.Clear();

    try
    {
        _fileTreeLogic.GetChildNodes(e.Node, true);
        e.Node.ExpandAll();

        SetChildrenCheckState(e.Node, isChecked);

    }
    finally
    {
        trvAvailableFiles.EndUpdate();
    }
    EnableEvents(true);
}

private void EnableEvents(bool bEnable)
{
    if(bEnable)
        cbWhatever.OnChecked += EventHandler;
    else
        cbWhatever.OnChecked -= EventHandler;
}
1 голос
/ 16 февраля 2011

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

Реальный взлом - это какой-то неясный способ предотвратить возникновение события в первый раз, но не в последующие. Будущие программисты обслуживания гарантированно поймут, как работает установка флага; они не гарантированно оценят «элегантность» вашего альтернативного подхода.

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