PropertyGrid, Difference between ComponentModel reflection (e.g PropertyDescriptor) and standard ref

来源:互联网 发布:mac iverilog 编辑:程序博客网 时间:2024/06/17 05:33

PropertyDescriptor:

提供类上的属性的抽象化。

 

 

发现属性 (Property) 的属性 (Attribute) 并提供对属性 (Property) 元数据的访问。
Use PropertyInfo is more efficient than PropertyDescriptor and easier to use.
PropertyDescriptor provides support for two main features:

1.  Data binding.  数据绑定。You can implement ICustomTypeDescriptor to supply "properties" for binding purposes.  The "properties" that you present can be generated dynamically and need not be the same as the actual properties of your class.  For example, DataRow might present the properties "FirstName" and "LastName" but there are no DataRow.FirstName and DataRow.LastName properties on the class.

2.  Design-time support.  设计支持。For example, doing fancy things with property grids in the Visual Studio Forms designer.  For example, you can implement components that add to or subtract from the sets of properties exposed by other components on the same design surface.
ComponentModel allows you to do a few DLR-type things, such as runtime-properties
In terms of usage, there are some other differences; ComponentModel only supports a single instance of any attribute on a member (unlike reflection, where multiple alike attributes are allows). And it is data-centric - so properties exist, as do events (primarily intended for change notification) - but there are no fields nor methods.

However, ComponentModel is not (directly) compatible with things like LINQ (MemberExpression in particular) - since this wants to bind to reflection data.

Finally, ComponentModel is highly used in the IDE by things like PropertyGrid (this is how things like the extra properties for tool-tips work), but equally almost all UI data binding happens via ComponentModel (since this allows the binding to support DataTable, classes, and anything else you can think of).

 

特别是,如果想要在Runtime是动态修改PropertyGrid的某些Readonly Property。则使用PropertyDesciptor.

If you want to expose collection properties, do not provide a ReadOnly attribute for them, otherwise theCollectionEditor will not be activated!

 

Sample Code:

1)public partialclass MyPropertyGrid :PropertyGrid

{
protected overridevoid OnSelectedObjectsChanged(EventArgs e)

 

}

 

2)How to: Take control over the Collection Editor's PropertyGrid

The PropertyGrid control is a very useful tool if you want to update object attributes at run-time in a elegant way. ThePropertyGrid provides some useful events to let you know what is going on. The problem occures for the collection properties when theCollection Editor form is shown. This form also provides a PropertyGrid control to edit any item from the current collection but we don't have access to any of known events.

http://dotnetfacts.blogspot.com/2008/05/how-to-take-control-over-collection.html

 

 

    {

        this.SetBrowsablePropertiesAsReadOnly(this.SelectedObject,this.isReadOnly);

        base.OnSelectedObjectsChanged(e);

    }

 

  ///<summary>

    /// Chnages the state of the ReadOnly attribute regarding the isReadOnly flag value.

    ///</summary>

    ///<param name="selectedObject">The current object exposed by the PropertyGrid.</param>

    ///<param name="isReadOnly">The current read-only state of the PropertyGrid.</param>

    private void SetBrowsablePropertiesAsReadOnly(object selectedObject,bool isReadOnly)

    {

        if (selectedObject !=null)

        {

            // Get all the properties of the selected object...

            PropertyDescriptorCollection props =TypeDescriptor.GetProperties(selectedObject.GetType());

 

            foreach (PropertyDescriptor propDescriptin props)

            {

                // Consider only the properties which are browsable and are not collections...

                if (propDescript.IsBrowsable && propDescript.PropertyType.GetInterface("ICollection",true) == null)

                {

                    ReadOnlyAttribute attr = propDescript.Attributes[typeof(ReadOnlyAttribute)]as ReadOnlyAttribute;

 

                    // If the current property has a ReadOnly attribute,

                    // update its state regarding the current ReadOnly state of the PropertyGrid.

                    if (attr !=null)

                    {

                        FieldInfo field = attr.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);

                        field.SetValue(attr, isReadOnly, BindingFlags.NonPublic | BindingFlags.Instance, null, null);

                    }

                }

            }

        }

    }

}

CollectionEditor 类
 
1)PropertyGrid中显示属性对话框,需要定义[Editor(typeof(ExcitationDataEditor), typeof(UITypeEditor))]   
UITypeEditor 类

提供可用于设计值编辑器的基类,这些编辑器可提供用户界面 (UI),用来表示和编辑所支持的数据类型的对象值。

 

private string _misfiringDataPath = string.Empty;        [Editor(typeof(ExcitationDataEditor), typeof(UITypeEditor))]        public string MisfiringDataPath         {            get { return _misfiringDataPath; }            set            {                _misfiringDataPath = value;                if (!string.IsNullOrEmpty(_misfiringDataPath))                {                    MisfiringData = File.ReadAllBytes(_misfiringDataPath);                }            }        }
class ExcitationDataEditor : UITypeEditor    {        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)        {            return UITypeEditorEditStyle.Modal;        }         public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)        {            string path = value as string;            var dlg = new OpenFileDialog();            if (dlg.ShowDialog() == DialogResult.OK)            {                path = dlg.FileName;            }             return path;        }    } 
 
2)创建在 PropertyGrid 中扩展的属性类型,请为 GetPropertiesSupportedGetProperties 的标准实现指定此 TypeConverter
[TypeConverter(typeof(ExcitationDataConverter))]    public class ExcitationDataBase { }
public class ExcitationDataConverter : ExpandableObjectConverter    {        public override bool CanConvertTo(ITypeDescriptorContext context,                                  Type destinationType)        {            return false;        }         public override object ConvertTo(ITypeDescriptorContext context,                               System.Globalization.CultureInfo culture,                               object value,                               Type destinationType)        {            return string.Empty;        }         public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)        {            return false;        }    }
PropertyInfo 类
原创粉丝点击