色編集アプリのUIとして、NumericUpDownとHScrollBarを使いました。 これらの連動をするとき、イベントハンドラの登録と解除をすることで無限ループを回避しました。
連動
NumericUpDownのUIを操作して値を変更したとき、HScrollBarのUIも変更したいのです。 また、逆も同じです。
WindowsFormアプリでは、UIの制御はイベントを用います。 該当のUIにそれぞれValueChangedイベントを登録しました。
ここに相手のUIの値を変更する処理を入れればいいだけです。
private void hScrollBar1_ValueChanged(object sender, EventArgs e)
{
numericUpDown1.Value = this.hScrollBar1.Value;
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
hScrollBar1.Value = this.numericUpDown1.Value;
}
無限ループ
これだと無限ループしてしまいます。 回避するためには、フラグを立てて強引に回避するか、イベントを解除すればよさそうです。
イベントの登録と解除
- 相手のUIのイベントを解除
- 相手のUIの値を設定
- 相手のUIのイベントを追加
public partial class ColorEditorForm : Form
{
System.EventHandler numHdl1;
System.EventHandler scrlHdl1;
public ColorEditorForm()
{
numHdl1 += new System.EventHandler(numericUpDown1_ValueChanged);
scrlHdl1 += new System.EventHandler(hScrollBar1_ValueChanged);
numericUpDown1.ValueChanged += numHdl1;
hScrollBar1.ValueChanged += scrlHdl1;
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
hScrollBar1.ValueChanged -= scrlHdl1;
hScrollBar1.Value = numericUpDown1.Value;
hScrollBar1.ValueChanged += scrlHdl1;
}
private void hScrollBar1_ValueChanged(object sender, EventArgs e)
{
numericUpDown1.ValueChanged -= numHdl1;
numericUpDown1.Value = hScrollBar1.Value;
numericUpDown1.ValueChanged += numHdl1;
}
}
2つのUIを連携させるとき、このような面倒があるという話でした。
フリーズしない?
わざと無限ループさせてみようと思って実験しました。 しかし、無事に実行できてしまいました。
- イベントの削除と再設定の部分をコメントアウト
- ビルドして実行
- NumericUpDownとHScrollBarをマウスやキーボードで適当に操作する
- 無限ループになってフリーズするとか、実行時エラーとか起きない なぜ?
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
// hScrollBar1.ValueChanged -= scrlHdl1;
hScrollBar1.Value = numericUpDown1.Value;
// hScrollBar1.ValueChanged += scrlHdl1;
}
private void hScrollBar1_ValueChanged(object sender, EventArgs e)
{
// numericUpDown1.ValueChanged -= numHdl1;
numericUpDown1.Value = hScrollBar1.Value;
// numericUpDown1.ValueChanged += numHdl1;
}
どこかで誰かが何かしら上手いことやってくれているのかしら。 怖いから元に戻しておこう。