2013-07-24 27 views
5

當需要更改System.Windows.Forms.DataGridView的當前行並允許我取消此更改時,我需要觸發事件。通過將EventArgs的Cancel-property設置爲true。防止C#DataGridView更改當前行的事件

我知道CurrentCellChanged(當事件被調用時該行已經改變)和RowLeave(不可能取消離開操作)事件,但都不能提供我所需要的。我也嘗試使用RowValidating事件,但是當該行正要驗證時(也不打算離開它),也會調用此事件,例如,當我致電<ParentForm>.Validate()時,會導致很多混淆。

是否有任何其他可能性或乾淨(呃)解決方案來獲得所需的行爲?

+0

,如果你不想讓用戶改變什麼用CellEndEdit?如果要防止用戶更改任何設置readonly = true – Ehsan

+0

根據您希望防止某種輸入KeyPress事件設置Handled = true的情況,將阻止非法字符或字符格式。 - 另外,不區分不同的單元格,因此您必須測試正在編輯哪個列或行以進行正確的測試。 –

+0

你可以擴展你想要達到的目標嗎? – CristisS

回答

0

嘗試很多不同的事情後,我來到了解決方案,最簡單,(對我來說)最有效的解決方案將是檢查的重點是在RowValidating事件DataGridView的哪些控制。該解決方案正好解決了我遇到的問題:例如,通過單擊其他按鈕引發RowValidating事件。即使當前行未發生變化(例如,通過單擊列標題對DataGridView進行排序),仍有一些特殊情況會導致RowValidating事件發生,但我認爲我可以忍受這些小問題。也許未來的.NET版本將實現一個DataGridView,並且可以取消RowLeaving事件。

1

我認爲你最好的選擇是使用RowValidating和bool條件來檢查你是否調用.Validate()。

編輯

根據您最後的評論,爲什麼不爲dataGridView.IsCurrentRowDirty添加一個檢查? 例如:

private void dataGridView1_RowValidating(object sender, DataGridViewCellCancelEventArgs e) { 
    if (dataGridView1.IsCurrentRowDirty) { 
     if (dataCheck()) 
      if (MessageBox.Show("Ok?", "Save?", MessageBoxButtons.YesNoCancel) == DialogResult.Cancel) { 
       e.Cancel = true; 
      } 
    } 
} 

如果沒有髒數據,不管是誰調用dataCheck將不進行驗證,並在MessageBox將不會出現。

編輯

,可隨時更換「如果」條款與任何檢查要包括一個用於dataGridView2。

如果您有非常複雜的需求,也可以擴展dataGridView控件。

編輯

現在我明白你的要求。我不認爲有一個快速和乾淨的解決方案。我會使用SelectionChanged事件並設置邏輯來防止更改。例如:

//rember the selection of the index 
private int _currentIndex; 
private bool _rollingBackSelection; 

private void SelectionChanged(...){ 
    //when changing back to the selection in dgv1 prevent dgv2 check 
    if (_rollingBackSelection) { 
     _rollingBackSelection = false; 
     return; 
    } 
    if (dgv2IsDirty()) { 
      var result = MessageBox.Show("Ok?", "Save?", MessageBoxButtons.YesNoCancel); 
      if (result == DialogResult.Cancel) { 
      _rollingBackSelection = true; 
      //rollback to the previous index 
      dgv1.Rows[_currentIndex].Selected = true; 
      return; 
      } 
      if (result == DialogResult.Yes) 
      dgv2Save(); 
     dgv2Load(); 
     _currentIndex = dgv1.SelectedRows[0].Index; 
    } 
} 

我覺得上面的東西是你最好的拍攝。

+0

不好的是RowValidating事件不僅僅是從Validate()方法調用的。例如,如果我點擊一個按鈕,它也被稱爲。當我說這會導致許多混亂時,這就是我的意思。 – Peter

+0

當你顯示MessageBox並在RowValidating中使用它時,你不能設置一個bool嗎?另外,你使用什麼事件來檢查底層數據表並顯示MessageBox,我想這是一個datagriview事件? – CristisS

+0

對不起,但我不明白顯示MessageBox時設置bool的原因。目前我使用RowValidating事件來檢查更改(DataTable.GetChanges()方法)並最終顯示消息框,如上面在我的問題中所述。但這就是我要問的事情,用於檢測和防止行更改的事件。 – Peter

1

剛跑進類似的問題,經過多次嘗試後,我唯一的工作就是使用「輸入並離開」來知道表單何時不活動以避免驗證 - 幸運的是,觸發順序在行\列級事件之前

HTH邁克 -

private bool IsActive = false; 

    private void dgbList_RowValidating(object sender, DataGridViewCellCancelEventArgs e) 
    { 
     if (IsActive) 
     { 
      if (Do_I_NeedTo_Cancel) 
       e.Cancel = true; 
     } 
    } 

    private void dgList_Leave(object sender, EventArgs e) 
    { 
     IsActive = false; 
    } 

    private void dgList_Enter(object sender, EventArgs e) 
    { 
     IsActive = true; 
    }