我在PropertyBag这个例子里对一个自定义的属性使用了[TypeConverter(ExpandableObjectConverter)],我的自定义属性是可以正常展开了,但是当我展开这个属性,并编辑了其中的一个成员之后,PropertyBag.SetValue并没有给调用,我就无从知道属性已经给修改了,请问这个问题该如何解决?

解决方案 »

  1.   

    SetValue看起来像是用来修改属性的方法,而不是事件,所以你怎么能通过这个知道属性修改了呢?
    要知道属性修改,应该监视值的变化。如果有现成的事件可用那就更好。
    我不知道你说的PropertyGrid是什么,不过应该是这样的。
    一般说来,事件应该是OnChange啊OnModify啊这种样子的。
      

  2.   

    首先呢,一般是因为属性编辑器直接对引用的属性值进行操作,所以不需要进行SetValue的操作,其次,如果想接受到这个消息的话,请继承UITypeEditor,重写该类的EditValue事件,在返回的时候返回一个新的Object(当然,Object的值还是原来的值)这一步的目的就是破除引用操作,强制调用SetValue。i.e.
    -----------------
    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        value = selectionControl.EditValue(context, provider, value);    List<MyListViewItem> l = new List<MyListViewItem>();
        if (value != null)
        {
            foreach (MyListViewItem var in (List<MyListViewItem>)value)
            {
                l.Add(var);
            }
        }
        return l;
    }
      

  3.   

    谢谢楼上的高人,但是上面的方法是必须点击属性边上的小按钮的,但是像size类型的属性,是没有小按钮的,可以把它展开,然后修改Width或者Height,修改完之后,PropertyBag.SetValue就会被调用,请问这是如何实现的呢?
      

  4.   

    通过查看调用堆栈,可以看到PropertyBag.SetValue是从PropertyGridInternal.PropertyDescriptorGridEntry.SetPropertyValue()进去的,SetPropertyValue()的第一个参数值是PropertyBag类型的,
    而修改我自己的属性,也可以调用到PropertyGridInternal.PropertyDescriptorGridEntry.SetPropertyValue(),但第一个参数值却是我自己的属性的类型,然后就不会调用PropertyBag.SetValue,请问有什么办法解决吗?
      

  5.   

    终于解决了,对自定义的属性使用了[TypeConverter(MyConverter)]
    MyConverter派生自TypeConverter,除了重载ConvertTo,ConvertFrom,CanConverTo,CanverFrom外,还需重载下面3个函数public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
            {
                return true;
            }
            
            public override PropertyDescriptorCollection GetProperties(
                                ITypeDescriptorContext context,
                                object value, Attribute[] attributes)
            {
                if (value is ButtonColor)
                    return TypeDescriptor.GetProperties(value, attributes);            return base.GetProperties(context, value, attributes);
            }        public override bool GetPropertiesSupported(ITypeDescriptorContext context)
            {
                return true;
            }