2016-04-15 44 views
0

我創建了一個自定義控件來編輯DataGridView單元格中的自定義值。我在這裏的例子如下: How to: Host Controls in Windows Forms DataGridView CellsDataGridView單元格中的自定義控件在編輯時拋出FormatException

我有一個自定義的數據類是綁定到DataGridView的對象列表的成員。

internal class CustomValue 
{ 
    // Some stuff is here. 
} 

我創建了一個自定義控件來編輯實現IDataGridViewEditingControl接口的單元格中的值。

internal partial class CustomValueEditControl : UserControl, IDataGridViewEditingControl 
{ 
     DataGridView m_dataGridView; 

     private bool m_valueChanged = false; 

     int m_rowIndex; 

     private CustomValue m_value; 

     public CustomValue Value 
     { 
      get 
      { 
       return m_value; 
      } 
      set 
      { 
       m_value = value; 
      } 
     } 

     public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle) 
     { 
     } 

     public DataGridView EditingControlDataGridView 
     { 
      get 
      { 
       return m_dataGridView; 
      } 
      set 
      { 
       m_dataGridView = value; 
      } 
     } 

     public object EditingControlFormattedValue 
     { 
      get 
      { 
       return this.Value.ToString(); 
      } 
      set 
      { 
       if (value is String) 
       { 
        CustomValue val; 
        if (CustomValue.TryParse((String)value, out val)) 
        { 
         this.Value = val; 
        } 
        else 
        { 
         this.Value = new CustomValue(); 
        } 
       } 
      } 
     } 

     public int EditingControlRowIndex 
     { 
      get 
      { 
       return m_rowIndex; 
      } 
      set 
      { 
       m_rowIndex = value; 
      } 
     } 

     public bool EditingControlValueChanged 
     { 
      get 
      { 
       return m_valueChanged; 
      } 
      set 
      { 
       m_valueChanged = value; 
      } 
     } 

     public bool EditingControlWantsInputKey(Keys keyData, bool dataGridViewWantsInputKey) 
     { 
      switch (keyData & Keys.KeyCode) 
      { 
       case Keys.Up: 
       case Keys.Down: 
        return true; 

       default: 
        return !dataGridViewWantsInputKey; 
      } 
     } 

     public Cursor EditingPanelCursor 
     { 
      get 
      { 
       return base.Cursor; 
      } 
     } 

     public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context) 
     { 
      return EditingControlFormattedValue; 
     } 

     public void PrepareEditingControlForEdit(bool selectAll) 
     { 
     } 

     public bool RepositionEditingControlOnValueChange 
     { 
      get 
      { 
       return false; 
      } 
     } 
} 

我已經設置了一個自定義的DataGridViewCell從DataGridViewTextBoxCell下降,從而所述細胞只顯示自定義值的字符串表示,直到它被編輯。

internal class CustomValueCell : DataGridViewTextBoxCell 
{ 

    public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) 
    { 
     base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle); 

     CustomValueEditControl customValueEditControl = DataGridView.EditingControl as CustomValueEditControl; 

     if (this.Value == null) 
     { 
      customValueEditControl.Value = (CustomValue)this.DefaultNewRowValue; 
     } 
     else 
     { 
      customValueEditControl.Value = (CustomValue)this.Value; 
     } 
    } 

    public override Type EditType 
    { 
     get 
     { 
      return typeof(CustomValueEditControl); 
     } 
    } 

    public override Type ValueType 
    { 
     get 
     { 
      return typeof(CustomValue); 
     } 
    } 

    public override Type FormattedValueType 
    { 
     get 
     { 
      return typeof(string); 
     } 
    } 

    public override object DefaultNewRowValue 
    { 
     get 
     { 
      return new CustomValue(); 
     } 
    } 
} 

我已經創建了一個自定義的DataGridViewColumn。

internal class CustomValueColumn : DataGridViewColumn 
{ 
    public CustomValueColumn() 
     : base(new CustomValueCell()) 
    { 
    } 

    public override object Clone() 
    { 
     CustomValueColumn clone = (CustomValueColumn)base.Clone(); 

     return clone; 
    } 

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

      base.CellTemplate = value; 
     } 
    } 
} 

單元格正確顯示自定義類型的值,並且我可以使用自定義控件編輯該值。當我離開編輯單元格時,出現System.FormatException:System.Convert.DefaultToType(IConvertable value,Type targetType,IFormatProvider provider)從'System.String'無效強制轉換爲'CustomValue'...

At它試圖將字符串轉換爲我的自定義值有什麼意義?這不應該由CustomValueEditControl.GetEditingControlFormattedValue來處理嗎?

+0

這已經有一段時間,因爲我不得不這樣的事情,但它聽起來像是你需要重寫'DataGridViewCell'的'GetFormattedValue'方法,看一下吧[這裏]的部分(https://開頭msdn.microsoft.com/en-us/library/aa730881(v=vs.80).aspx#dtH1)(接近中間) –

+0

我試過了。我認爲DataGridViewTextBoxCell已經覆蓋了從對象返回一個字符串。 –

回答

1

它在什麼時候試圖將字符串強制轉換爲我的自定義值?這不應該由CustomValueEditControl.GetEditingControlFormattedValue來處理嗎?

沒錯。但是你基於的示例沒有正確處理它。如果返回string(其中EditingControlFormattedValue屬性確實)

public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context) 
{ 
    if ((context & DataGridViewDataErrorContexts.Parsing) != 0) 
    { 
     // Here you should not return string, but your value 
     return Value; 
    } 
    return EditingControlFormattedValue; 
} 

,那麼DataGridView會嘗試將其轉換爲CustomValue對象:你應該使用這樣的事情。該示例的工作原因是DateTime已關聯TypeConverter而您的班級顯然沒有。

+0

我想我一直在這條路上。如果GetEditingControlFormattedValue返回一個CustomValue,那麼我得到一個System.ArgumentException:單元格的格式化值有錯誤的類型。 如果將單元格的FormattedValueType屬性更改爲CustomValue,則單元格在未編輯單元格時不顯示字符串表示形式。 –

+0

請參閱答案中的代碼片段 - 這就是你需要做的。添加'if'語句並以不同的方式處理'DataGridViewDataErrorContexts.Parsing'標誌, –

0

所以我最終通過實現一個TypeConverter類來解決這個問題。

internal class CustomValueTypeConverter : TypeConverter 
{ 
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 
    { 
     if (sourceType == typeof(string)) 
     { 
      return true; 
     } 

     return base.CanConvertFrom(context, sourceType); 
    } 

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) 
    { 
     if (destinationType == typeof(string)) 
     { 
      return true; 
     } 

     return base.CanConvertTo(context, destinationType); 
    } 

    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) 
    { 
     if (value is string) 
     { 
      CustomValue customValue; 

      if (CustomValue.TryParse((string)value, out customValue)) 
      { 
       return customValue; 
      } 
     } 

     return base.ConvertFrom(context, culture, value); 
    } 

    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) 
    { 
     if (destinationType == typeof(string)) 
     { 
      value.ToString(); 
     } 

     return base.ConvertTo(context, culture, value, destinationType); 
    } 
} 

然後,我不得不使用TypeConverterAttribute來修飾CustomValue類。

[TypeConverter(typeof(CustomValueTypeConverter))] 
internal class CustomValue 
{ 
    // Some stuff here. 
} 
相關問題