2016-04-15 43 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. 
} 
相关问题