2013-02-18 59 views
0

我正在使用DataGridView,并使用CellValueChanged事件。掩盖UI事件的最佳方法是什么?

我不想当代码更改单元格值时触发此事件。但是,我希望在用户编辑它时触发它。

这就是为什么我附上我的单元格的值更改操作用下面的代码:

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中Events的解决方案,而不仅仅是DataGridView。

所以我的问题是:

什么是正确掩盖UI活动,避免不必要的火灾事件的最好的提示?

+0

[通过用户交互引发的事件和我自己的代码区分]的可能重复(http://stackoverflow.com/questions/729897/differentiating-between-events-raised-by-user-interaction-and -my-own-code) – 2013-02-18 14:10:58

+0

类似[CellBeginEdit](http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.cellbeginedit(v = vs.110).aspx)? – 2013-02-18 14:12:24

+0

感谢您的指点。对不起,链接的问题很遗憾地回答我的问题。我无法使用CellBeginEdit:它在用户开始键入单元格时立即触发。 – Larry 2013-02-18 14:17:01

回答

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(); 
    } 
} 
0

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

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

0

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

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

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

+0

Thanks.This是一个完全“手动”的DataGridView。没有数据源或数据绑定机制。我会尝试你使用CellEndEdit的建议。 – Larry 2013-02-18 16:49:42

+0

我的意思是,如果我没有一个数据绑定机制,我自己构建它。这是更多的代码编写,但我认为这是值得的努力,特别是如果你开发自己的框架,可以用于许多不同的项目 – 2013-02-18 22:39:17

+0

同意。我的要求是一些单元格需要特定的颜色,具体取决于它们的值,一些单元格从/到只读模式切换,其他单元格是计算值,再加上网格本身进行转置,所以列是我的数据模型中的一行...逻辑非常复杂,我不得不手动设计和填充网格。我必须承认它比看起来更令人愉快,并且它可以非常干净地实现。我甚至发现了一些可重复使用的代码。我不认为3D派对组件需要更少的工作。以这种方式重新发现DataGridView使我感觉像在Excel中编码:) – Larry 2013-02-19 07:38:03

相关问题