2016-04-15 7 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; 
      } 
     } 
} 

私はそれが編集されるまで、セルがちょうどカスタム値の文字列表現を表示するようDataGridViewTextBoxCellから下降カスタムのDataGridViewCellを設定しています。

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型、タイプtargetType、IFormatProviderプロバイダ)で '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によって処理されませんか?

正確に。しかし、あなたが基づいているサンプルは正しく処理しません。あなたは(EditingControlFormattedValueプロパティがありません)stringを返す場合は、DataGridViewCustomValueオブジェクトに変換しようとします

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

:あなたはこのようなものを使用する必要があります。この例は、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. 
} 
関連する問題