2013-02-18 71 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

相關問題