0

私は DataGridView を使用しており、CellValueChangedイベントを使用しています。

コードでセルの値を変更したときに、このイベントがトリガーされないようにします。ただし、ユーザーが編集したときにトリガーされるようにします。

そのため、セル値の変更操作を次のコードで囲みます。

void changeCellOperation()
{
    dgv.CellValueChanged -= new DataGridViewCellEventHandler(dgv_CellValueChanged);

    ...
    cell.Value = myNewCellValue
    ...

    dgv.CellValueChanged += new DataGridViewCellEventHandler(dgv_CellValueChanged);
}

DataGridView セルがこのように更新されるいくつかの異なる機能を持つようになりました。

これらの関数はさまざまな場所から呼び出され、入れ子にすることができるため、不要なイベントの再アクティブ化を避けるために、このコードをそのままにしておく余裕はありません。

だから私はこのようになりました:

int valueChangedEventMask = 0;

void changeCellOperation()
{
    valueChangedEventMask++;

    ...
    cell.Value = myNewCellValue
    ...

    valueChangedEventMask--;
}

void dgv_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    if (valueChangedEventMask > 0)
        return

    ...
}

これはうまくいきます。また、イベント自体の内部を含め、呼び出しがネストされている場合。

しかし、このCellValueChangedイベントは今では何の理由もなく何度も発生しています

このパターンに対処しなければならないことが多いため、DataGridView だけでなく、UI のイベント全般に適用できるソリューションを探しています。

だから私の質問は:

UI イベントを正しくマスクし、不要なイベントの発生を回避するための最良のヒントは何ですか?

4

3 に答える 3

0

CellEndEditの代わりに使用できますCellValueChange。メソッドが何をするのかわかりませんが、セルの値が変更されていなくても、セルの編集モードを終了するたびに起動dgv_CellValueChangedされることに注意してください。CellEndEditこれは、値が変化しないときにメソッドを実行したくない場合は、セルの現在の値を追跡する必要があることを意味します。

ユーザーはキーボードだけを使用できるため、CellClick などのマウスに関連するイベントは避けます。

とにかく、私は通常、ユーザー インターフェイスからロジックを分離することによって、この種の問題を回避します。つまり、フォームにバインドされた別のクラスを作成します。MVVM (必要に応じて WinForms に独自のバージョンを実装できます) または古き良きMVCをご覧ください。

于 2013-02-18T15:26:24.917 に答える
0

CellValueChangedUI イベントではなく、プロパティ変更イベントです。つまり、ユーザー入力とプログラムによる変更を区別するために使用することはできません。Subscriber/unsucscribe または flag+/- または BeginEdit/EndEdit と同様の手法をいつでも使用できますが、別の (より良い) アプローチを見つける必要があるかもしれません。たとえば、チェックボックスの場合、のClick代わりにイベントを使用できます。これはChanged、(驚き!) ユーザーがクリックしたときに通知され、それ以外の場合はCheckedプログラムで安全に値を変更できるためです。

DataGridView最も簡単な場合はChanged、いくつかのフラグを使用することです (編集の開始時に設定され、編集の終了時にリセットされます - を参照CellBeginEdit/CellEndEdit)。

于 2013-02-18T14:25:13.500 に答える
0

最終的に、両方のソリューションを非常に単純なソリューションに混ぜ合わせました。私はカウンターを使用し、マスクしたいイベントのみをフック/フック解除します。

EventMask valueChangedEventMask;

// In the class constructor
valueChangedEventMask = new EventMask(
    () => { dgv.CellValueChanged += new DataGridViewCellEventHandler(dgv_CellValueChanged); },
    () => { dgv.CellValueChanged -= new DataGridViewCellEventHandler(dgv_CellValueChanged); }
);

// The value change operation I want to hide from the event
void changeCellOperation()
{
    valueChangedEventMask.Push();

    ...
    cell.Value = myNewCellValue
    ...

    valueChangedEventMask.Pop();
}

// The class
public class EventMask
{
    Action hook;
    Action unHook;

    int count = 0;

    public EventMask(Action hook, Action unHook)
    {
        this.hook = hook;
        this.unHook = unHook;
    }

    public void Push()
    {
        count++;
        if (count == 1)
            unHook();
    }

    public void Pop()
    {
        count--;
        if (count == 0)
            hook();
    }
}
于 2013-02-18T15:59:41.187 に答える