Как игнорировать простые события, возникающие при изменении состояния элементов управления в C # Windows Forms? - PullRequest
5 голосов
/ 07 июля 2011

Я создаю простую форму в C # Windows Forms и сталкиваюсь с общей ситуацией, когда один элемент управления может изменять состояние другого, но события обоих элементов управления вызывают другой метод.

Например, рассмотрим Checkbox и NumericUpDown, где состояние или значение любого из них должно инициировать что-то для перерисовки. NumericUpDown зависит от Checkbox, означающего, что его можно отключить или игнорировать, если не отмечен Checkbox.

Однако пользователю удобно изменить значение NumericUpDown и автоматически проверить Checkbox, если оно еще не было.

Итак, вот методы, о которых идет речь:

private void chkState_CheckedChanged(object sender, EventArgs e)
{
    RedrawStuff();
}

private void numStateValue_ValueChanged(object sender, EventArgs e)
{
    if (!chkState.Checked)
        chkState.Checked = true;
    RedrawStuff();
}

Проблема, конечно, в том, что при изменении значения NumericUpDown дважды запускается RedrawStuff().

Мой обходной путь - ввести логическое значение, где я могу эффективно отрицать это поведение, но иногда оно может запутаться:

bool _preventStateChange;

private void chkState_CheckedChanged(object sender, EventArgs e)
{
    if (_preventStateChange)
        return;
    RedrawStuff();
}

private void numStateValue_ValueChanged(object sender, EventArgs e)
{
    _preventStateChange = true;
    if (!chkState.Checked)
        chkState.Checked = true;
    RedrawStuff();
    _preventStateChange = false;
}

Это лучший способ справиться с этой ситуацией?

Ответы [ 4 ]

6 голосов
/ 07 июля 2011

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

private void chkState_CheckedChanged(object sender, EventArgs e)
{
    if (chkState.Focused)
        RedrawStuff();
}

private void numStateValue_ValueChanged(object sender, EventArgs e)
{
    if (!chkState.Checked)
        chkState.Checked = true;

    if (numStateValue.Focused)
        RedrawStuff();
}

Таким образом, каждый объектзависит только от самого себя.

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

1 голос
/ 07 июля 2011

Я думаю, что CheckedChanged на CheckBox не срабатывает, если управление отключено, поэтому сделайте следующее:

private void numStateValue_ValueChanged(object sender, EventArgs e) 
{     
    if (!chkState.Checked)      
    {
        chkState.Enabled = false;
        chkState.Checked = true;    
        chkState.Enabled = true;
    }
    RedrawStuff();
} 

Если я неправильно помню, откажитесь от голосования.

1 голос
/ 07 июля 2011

Вы можете «отсоединить» события изменения в начале вашего метода «RedrawStuff» и подключить их снова в конце.

</p>

<p>private void RedrawStuff()
{
    // un-wire the change events
    chkState.CheckedChanged -= new System.EventHandler(chkState_CheckedChanged);
    numStateValue.ValueChanged -= new System.EventHandler(chkState_CheckedChanged);</p>

<code>/*
  .... do you thing...including setting the state of both / either controls
       based on the state of things, without fear of triggering recursive changes...
*/

// wire them back up
chkState.CheckedChanged += new System.EventHandler(chkState_CheckedChanged);
numStateValue.ValueChanged += new System.EventHandler(chkState_CheckedChanged);
</code>

}

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

1 голос
/ 07 июля 2011

Просто переместите RedrawStuff(); в другое предложение. Таким образом, он вызывается в обеих ситуациях, но только один раз.

private void chkState_CheckedChanged(object sender, EventArgs e)
{
    RedrawStuff();
}

private void numStateValue_ValueChanged(object sender, EventArgs e)
{
    if (!chkState.Checked)
        chkState.Checked = true;
    else
        RedrawStuff();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...