2016-05-19 34 views
0

我有一個用戶控件,我需要添加爲DataGridView中的列。我遵循here所示的說明。DataGridViewColumn EditingControl編輯的值不反映

控件被正確添加,當我單擊單元格時,用戶控件顯示出來。但是,現在當我點擊其他地方時,編輯的值不會反射回DataGridView。代碼如下。 MoneyTextBox是用戶控件。

class MoneyTextBoxColumn : DataGridViewColumn 
{ 
    public MoneyTextBoxColumn() : base(new MoneyTextBoxCell()) 
    { 
    } 

    public override DataGridViewCell CellTemplate 
    { 
     get 
     { 
      return base.CellTemplate; 
     } 
     set 
     { 
      // Ensure that the cell used for the template is a MoneyTextBoxCell. 
      if (value != null && !value.GetType().IsAssignableFrom(typeof(MoneyTextBoxCell))) 
      { 
       throw new InvalidCastException("Must be a MoneyTextBoxCell"); 
      } 
      base.CellTemplate = value; 
     } 
    } 
} 

public class MoneyTextBoxCell : DataGridViewTextBoxCell 
{ 

    public MoneyTextBoxCell() : base() 
    { 
    } 

    public override void InitializeEditingControl(int rowIndex, object 
     initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) 
    { 
     // Set the value of the editing control to the current cell value. 
     base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle); 
     MoneyTextBoxEditingControl ctl = DataGridView.EditingControl as MoneyTextBoxEditingControl; 
     if (this.RowIndex >= 0) 
     { 
      if (!object.ReferenceEquals(this.Value, DBNull.Value) && this.Value != null && this.Value.ToString() != string.Empty) 
      { 
       ctl.Text = this.Value.ToString(); 
      } 
      else 
      { 
       ctl.Text = this.DefaultNewRowValue.ToString(); 
      } 
     } 
    } 


    public override Type EditType 
    { 
     get 
     { 
      // Return the type of the editing control that MoneyTextBoxCell uses. 
      return typeof(MoneyTextBoxEditingControl); 
     } 
    } 

    public override Type ValueType 
    { 
     get 
     { 
      // Return the type of the value that MoneyTextBoxCell contains. 

      return typeof(string); 
     } 
    } 

    public override object DefaultNewRowValue 
    { 
     get 
     { 
      return "0.00"; 
     } 
    } 
} 

class MoneyTextBoxEditingControl : MoneyTextBox, IDataGridViewEditingControl 
{ 
    DataGridView dataGridView; 
    private bool valueChanged = false; 
    int rowIndex; 

    public MoneyTextBoxEditingControl() 
    { 
    } 

    // Implements the IDataGridViewEditingControl.EditingControlFormattedValue 
    // property. 
    public object EditingControlFormattedValue 
    { 
     get 
     { 
      return this.Value; 
     } 
     set 
     { 
      this.MText = (string)value; 
     } 
    } 

    // Implements the 
    // IDataGridViewEditingControl.GetEditingControlFormattedValue method. 
    public object GetEditingControlFormattedValue(
     DataGridViewDataErrorContexts context) 
    { 
     return EditingControlFormattedValue; 
    } 

    // Implements the 
    // IDataGridViewEditingControl.ApplyCellStyleToEditingControl method. 
    public void ApplyCellStyleToEditingControl(
     DataGridViewCellStyle dataGridViewCellStyle) 
    { 
     this.Font = dataGridViewCellStyle.Font; 
    } 

    // Implements the IDataGridViewEditingControl.EditingControlRowIndex 
    // property. 
    public int EditingControlRowIndex 
    { 
     get 
     { 
      return rowIndex; 
     } 
     set 
     { 
      rowIndex = value; 
     } 
    } 

    // Implements the IDataGridViewEditingControl.EditingControlWantsInputKey 
    // method. 
    public bool EditingControlWantsInputKey(
     Keys key, bool dataGridViewWantsInputKey) 
    { 
     // Let the DateTimePicker handle the keys listed. 
     switch (key & Keys.KeyCode) 
     { 
      case Keys.Left: 
      case Keys.Up: 
      case Keys.Down: 
      case Keys.Right: 
      case Keys.Home: 
      case Keys.End: 
      case Keys.PageDown: 
      case Keys.PageUp: 
       return true; 
      default: 
       return !dataGridViewWantsInputKey; 
     } 
    } 

    // Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit 
    // method. 
    public void PrepareEditingControlForEdit(bool selectAll) 
    { 
     // No preparation needs to be done. 
    } 

    // Implements the IDataGridViewEditingControl 
    // .RepositionEditingControlOnValueChange property. 
    public bool RepositionEditingControlOnValueChange 
    { 
     get 
     { 
      return false; 
     } 
    } 

    // Implements the IDataGridViewEditingControl 
    // .EditingControlDataGridView property. 
    public DataGridView EditingControlDataGridView 
    { 
     get 
     { 
      return dataGridView; 
     } 
     set 
     { 
      dataGridView = value; 
     } 
    } 

    // Implements the IDataGridViewEditingControl 
    // .EditingControlValueChanged property. 
    public bool EditingControlValueChanged 
    { 
     get 
     { 
      return valueChanged; 
     } 
     set 
     { 
      valueChanged = value; 
     } 
    } 

    // Implements the IDataGridViewEditingControl 
    // .EditingPanelCursor property. 
    public Cursor EditingPanelCursor 
    { 
     get 
     { 
      return base.Cursor; 
     } 
    }  
} 

如何將編輯後的值傳播回DataGridView?

我變成了接近實現我想要的東西是如下所示手動分配的DetachEditingControl法的價值的唯一方法,但是,我得到一個System.InvalidOperationException與消息Operation is not valid due to the current state of the object,當選擇了最後一排。

public override void DetachEditingControl() 
{ 
    DataGridView dataGridView = this.DataGridView; 
    if (dataGridView == null || dataGridView.EditingControl == null) 
    { 
     throw new InvalidOperationException("Cell is detached or its grid has no editing control."); 
    } 
    MoneyTextBoxEditingControl ctl = DataGridView.EditingControl as MoneyTextBoxEditingControl; 
    dataGridView.CurrentCell.Value = ctl.EditingControlFormattedValue; 


    base.DetachEditingControl(); 
} 

我的要求是隻將編輯的值返回到DataGridView。 TIA。

+0

我相信正確的答案是通過調用編輯控件中的網格的NotifyCurrentCellDirty(true)來通知網格的變化,並且接受的答案是完全誤導的! –

+0

爲了確保您看看所有標準編輯控件類型的源代碼,您將看到執行相同工作的部分代碼。例如在'DataGridViewComboBoxEditingControl'中,有['OnSelectedIndexChange']的覆蓋(http://referencesource.microsoft.com/System.Windows.Forms/winforms/Managed/System/WinForms/DataGridViewComboBoxEditingControl.cs.html#d82a226eee5ab67c)在該方法中,您可以看到包含'this.dataGridView.NotifyCurrentCellDirty(true);' –

+0

的方法調用您還可以查看[如何:在Windows窗體DataGridView單元中託管控件](https://msdn.microsoft .com/en-us/library/7tas5c80(v = vs.110).aspx),並查看樣例中編輯控件時如何調用this.EditingControlDataGridView.NotifyCurrentCellDirty(true);方法。 –

回答

1

如果DataGridView是數據綁定的,您將無法修改單元格的內容。相反,你應該修改數據綁定對象。

MyObj obj = (MyObj)dataGridView.CurrentRow.DataBoundItem; 
obj.MyProperty = newValue; 

綁定的對象應該實現INotifyPropertyChanged,使這一變化反映在DataGridView

您可能會發現這個帖子的一些其他的解決辦法:你可以通過一個DataGridViewRow的DataBoundItem訪問該對象 How to programmatically set cell value in DataGridView?

+1

謝謝,這解決了我的問題。 – Fahad