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事件现在无缘无故地被触发了太多次

因为我经常不得不处理这种模式,所以我正在寻找一种可以普遍适用于 UI 中的事件的解决方案,而不仅仅是 DataGridView。

所以我的问题是:

正确屏蔽 UI 事件并避免不必要的事件触发的最佳技巧是什么?

4

3 回答 3

0

CellValueChanged不是 UI 事件,而是属性更改事件。这意味着您不能使用它来区分用户输入和程序更改。您始终可以使用订阅者/取消订阅或标记+/- 或 BeginEdit/EndEdit 类似的技术,但也许您必须找到另一种(更好的)方法。例如,在复选框的情况下,您可以使用Clickevent 而不是,因为(惊喜!)它会告诉您用户何时单击它,否则会以编程Changed方式安全地更改值。Checked

DataGridView最简单的情况下,将使用Changed一些标志(将在编辑开始时设置并在结束时重置 - 参见,CellBeginEdit/CellEndEdit)。

于 2013-02-18T14:25:13.500 回答
0

您可以使用CellEndEdit而不是CellValueChange. 我不知道您的方法是做什么的dgv_CellValueChanged,请注意CellEndEdit每次退出单元格的编辑模式时都会触发它,即使它的值没有更改。这意味着如果您不希望在值不变时执行该方法,则必须跟踪单元格的当前值。

我会避免与鼠标相关的事件,例如 CellClick,因为您的用户只能使用键盘。

无论如何,我通常通过将逻辑与用户界面分离来避免此类问题,即我编写了一个绑定到表单的单独类。看看MVVM(如果你愿意,你可以在 WinForms 中实现你自己的版本)或好的旧MVC

于 2013-02-18T15:26:24.917 回答
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 回答