Проблема в событии CheckedChanged - PullRequest
8 голосов
/ 19 марта 2010

У меня есть флажок, и я подписался на событие CheckedChanged. Обработчик выполняет там некоторые операции. Я устанавливаю и снимаю флажок программно (например, chkbx_Name.Checked = true), и событие CheckedChanged запускается.

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

Ответы [ 5 ]

13 голосов
/ 19 марта 2010

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

check1.CheckChanged -= check1_CheckChanged;

тогда вы можете программно установить значение без флажка, запускающего его событие CheckChanged:

check1.Checked = true;

затем переподписаться:

check1.CheckChanged += check1_CheckChanged;

[РЕДАКТИРОВАТЬ: 29 марта 2012 г.]

Проблема с подходом Tanvi заключается в том, что вам нужно перехватить все источники ручной проверки или снять отметку . Не то чтобы их было слишком много (это только от щелчка мышью и от нажатия клавиши пробела), но вы должны рассмотреть возможность вызова рефакторированного события из MouseClick и KeyUp (обнаружение пробела)

Лучше, чтобы CheckBox (любой элемент управления) не зависел от источника пользовательского ввода (клавиатуры, мыши и т. Д.), Поэтому для этого я просто сделаю программную настройку CheckBox действительно программной. Например, вы можете перенести программную настройку свойства в метод расширения:

static class Helper
{
    public static void SetCheckProgrammatically(
        this CheckBox c, 
        EventHandler subscribedEvent, bool b)
    {            
        c.CheckedChanged -= subscribedEvent; // unsubscribe
        c.Checked = b;
        c.CheckedChanged += subscribedEvent; // subscribe
    }
}

Используя этот подход, ваш код может аккуратно реагировать как на ввод данных с мыши, так и с клавиатуры пользователя только через одно событие, т.е. через CheckChanged. Нет дублирования кода, нет необходимости подписываться на несколько событий (например, клавиатура, проверка / снятие флажка CheckBox нажатием пробела)

5 голосов
/ 19 марта 2010

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

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

class Foo : Form {
    private bool checkedProgrammatically = false;

    void someMethod() {
        // ...
        checkedProgrammatically = true;
        checkBox1.Checked = true;
        checkedProgrammatically = false;
        // ...
    }

    private void checkBox1_CheckChanged(object sender, EventArgs e) {
        if (checkedProgrammatically) return;
        // ...
    }
}
1 голос
/ 06 февраля 2012

Вы можете использовать событие MouseClick , и в этой проверке проверяется состояние флажка. Таким образом, он не будет запускаться программно, он будет вызываться только тогда, когда пользователь вручную ставит или снимает флажок.

1 голос
/ 19 августа 2010

Извините, я не могу просто комментировать ответ Майкла Буэна из-за того, что я здесь новичок (без репутации), но из-за того, что оно того стоит, я решительно предпочитаю его решение Йоханнесу Ресселю по нескольким причинам.

1) переменная checkedProgrammatics немного слишком близка к глобальной. Нет ничего, что могло бы остановить другой метод, случайно установив его в true, и все ваши события были остановлены.

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

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

Я широко использовал оба метода, и мне кажется, что Майкл намного легче в долгосрочной перспективе.

0 голосов
/ 19 марта 2010

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

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