DataGridViewComboBoxColumn 绑定对象集合时存在BUG?

     DataGridview 绑定的是对象集合,里面有一列是下拉列表,也用集合绑定,一切看上去很美好,可是当我改变选择下拉列表时,却发生BUG。字符串不能转成对象!不知是DataGridview里的对应的下拉列表列保存的是字符串,还是下拉列表保存的是字符串。
    

   查google 得知,下拉列表是以模板的方式进行编辑,这有点以前web      下的datagrid

(既然编辑的时候用另一种控件,为何显视时不直接使用label算了,就象Infragistics UltraGrid)。于是创建一下模板列继承DataGridViewComboBoxCell。果然有ParseFormattedValue这个方法。跟踪,原来formattedValue传进来时是一个字符串类型。看来问题很容易解决吗,于是转成对象:

  public override object ParseFormattedValue(object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter)
        
{
              ComboBox comboBox 
= base.DataGridView.EditingControl as ComboBox;
              formattedValue 
= (BizObject)comboBox.SelectedItem;
            
return base.ParseFormattedValue(formattedValue, cellStyle, formattedValueTypeConverter, valueTypeConverter);
        }


这下好了,出现了新的问题

类型转化错误!由于调用了内部类,这下子跟踪不了了,反编译System.Windows.Forms,得到下面方法:

public override object ParseFormattedValue(object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter)
{
      
if (valueTypeConverter == null)
      
{
            
if (this.ValueMemberProperty != null)
            
{
                  valueTypeConverter 
= this.ValueMemberProperty.Converter;
            }

            
else if (this.DisplayMemberProperty != null)
            
{
                  valueTypeConverter 
= this.DisplayMemberProperty.Converter;
            }

      }

      
if (((this.DataManager != null&& ((this.DisplayMemberProperty != null|| (this.ValueMemberProperty != null))) || (!string.IsNullOrEmpty(this.DisplayMember) || !string.IsNullOrEmpty(this.ValueMember)))
      
{
            
object obj1 = base.ParseFormattedValueInternal(this.DisplayType, formattedValue, cellStyle, formattedValueTypeConverter, this.DisplayTypeConverter);
            
object obj2 = obj1;
            
if (!this.LookupValue(obj2, out obj1))
            
{
                  
if (obj2 != DBNull.Value)
                  
{
                        
throw new FormatException(string.Format(CultureInfo.CurrentCulture, SR.GetString("Formatter_CantConvert"), new object[] { obj1, this.DisplayType }));
                  }

                  
return DBNull.Value;
            }

            
return obj1;
      }

      
return base.ParseFormattedValueInternal(this.ValueType, formattedValue, cellStyle, formattedValueTypeConverter, valueTypeConverter);
}


internal object ParseFormattedValueInternal(Type valueType, object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter)
{
      
if (cellStyle == null)
      
{
            
throw new ArgumentNullException("cellStyle");
      }

      
if (this.FormattedValueType == null)
      
{
            
throw new FormatException(SR.GetString("DataGridViewCell_FormattedValueTypeNull"));
      }

      
if (valueType == null)
      
{
            
throw new FormatException(SR.GetString("DataGridViewCell_ValueTypeNull"));
      }

      
if ((formattedValue == null|| !this.FormattedValueType.IsAssignableFrom(formattedValue.GetType()))
      
{
            
throw new ArgumentException(SR.GetString("DataGridViewCell_FormattedValueHasWrongType"), "formattedValue");
      }

      
return Formatter.ParseObject(formattedValue, valueType, this.FormattedValueType, (valueTypeConverter == null? this.ValueTypeConverter : valueTypeConverter, (formattedValueTypeConverter == null? this.FormattedValueTypeConverter : formattedValueTypeConverter, cellStyle.FormatProvider, cellStyle.NullValue, cellStyle.IsDataSourceNullValueDefault ? Formatter.GetDefaultDataSourceNullValue(valueType) : cellStyle.DataSourceNullValue);
}

 

在方法ParseFormattedValueInternal 里有一个属性:  this.FormattedValueType 是字符串型,而我传进去的已经变成了对象型了,所以在这里报错了。

 

属性 FormattedValueType覆盖了基类, 这里已经变成了字符串类型

public override Type FormattedValueType
{
      
get
      {
            
return DataGridViewComboBoxCell.defaultFormattedValueType;
      }
}
这个defaultFormattedValueType值就不知从哪里设来的了。 然而基类 FormattedValueType类里的this.ValueType而反是我需要的对象的类型。
[Browsable(false)]
public virtual Type FormattedValueType
{
      
get
      {
            
return this.ValueType;
      }
}

于是用这个基类 FormattedValueType重新覆盖。结果错误是没有了,可下拉列表列全是空白。不过我点击下拉列表,却是程序需要的选择。看来显示又出现了问题.

 

最后的解决方法是:BizObject 是我对象的基类

  public override object ParseFormattedValue(object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter)
        {
            ComboBox comboBox 
= base.DataGridView.EditingControl as ComboBox;
            formattedValue 
= (BizObject)comboBox.SelectedItem;
            
return formattedValue;

        }

虽然没有问题了,但是直接反回而忽略其它几个参数,感觉不是很自然。不知大家有没有更好的方法。

posted @ 2006-08-28 10:51 瑞德船长 阅读(3045) 评论(3)  编辑 收藏 网摘 所属分类: DotNet 2.0

  回复  引用    
#1楼2006-08-28 14:21 | tianya[未注册用户]
我也觉得它的实现有缺陷 ,只支持基本类型的绑定,我的解决办法是绕开它,
将DataGridViewComboBoxColumn的DataPropertyName改为对象ID,value指定为对象的ID,绑定类再根据ID值将对象找出来.

  回复  引用  查看    
#2楼2006-08-28 22:13 | 曲欧      
直接为此下拉控件单独指定数据源,即可绕开文中的formattedValue问题。你如此进行对象类型的转换,涉及到数据绑定这类和数据库打交道的控件时最好避免 。



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 488117




相关文章:

相关链接: