PropertyGrid可浏览未找到实体框架创建的属性,如何找到它? [英] PropertyGrid Browsable not found for entity framework created property, how to find it?

查看:257
本文介绍了PropertyGrid可浏览未找到实体框架创建的属性,如何找到它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



但是,除非可以在对象创建上设置可浏览,否则我的代码可以改变Browsable不会工作。现在我可以手动添加可浏览,但是当我对我的实体进行更改(仍在开发项目时,对实体进行了很多更改),我添加的任何其他属性都将消失。



我试图用其他方式设置[Browsable(true)]两种方式: http:// ardalis。 com / add-attributes-to-generated-classes http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/617ebfca-0f68-4b90-83fd-0da758fadbd0/



两者似乎都是正确地设置了Browsable,但是当我通过属性描述符中的属性循环时,它并不存在(对我来说)。

  String fieldname =browsable; //我也编辑description
PropertyDescriptor pd = TypeDescriptor.GetProperties(o.GetType())[propertyName];
object attrib = null;
AttributeCollection attribs = pd.Attributes;

foreach(属性a属性)
{
if(a.GetType()== attributeType)
{
attrib = a;
break;
}
}
//微软文档引导人们相信以下代码行将找到所需的属性
//否定上述更完整的foreach语句的需要。
//但是,即使它不存在也似乎找到属性。 found属性
//的设置值将导致随机内存被更改,这将导致非常不可预测的行为。
// attrib = pd.Attributes [t];

if(attrib!= null)
{
//包含值的定位字段
FieldInfo field = attrib.GetType()GetField(fieldName,BindingFlags。非公开| BindingFlags.Instance);
if(field!= null)
{
if(field.FieldType == value.GetType())
{
//将字段设置为所需值
field.SetValue(attrib,value);
}
}
}
else
{
抛出新异常(Attribute(+ attributeType.Name +) + propertyName +));
}

所以我继续收到我抛出的异常,如果没有找到可以浏览 - 但是,如果没有在Model.Designer.cs中首先设置。



以下是我的Model.Designer.cs的样子。

  ///< summary> 
///没有元数据文档可用。
///< / summary>
[EdmScalarPropertyAttribute(EntityKeyProperty = false,IsNullable = true)]
[DataMemberAttribute()]
[Browsable(false)] //这可以,但如果更改我的实体,则会消失
public Nullable< global :: System.TimeSpan> SignoutAfter
{
get
{
return _SignoutAfter;
}
set
{
OnSignoutAfterChanging(value);
ReportPropertyChanging(SignoutAfter);
_SignoutAfter = StructuralObject.SetValidValue(value);
ReportPropertyChanged(SignoutAfter);
OnSignoutAfterChanged();
}
}
private Nullable< global :: System.TimeSpan> _SignoutAfter;
partial void OnSignoutAfterChanging(Nullable< global :: System.TimeSpan> value);
partial void OnSignoutAfterChanged();

所以我需要一种方式1.添加浏览实体,当我编辑它们总是也许编辑t4,但我甚至不知道从哪开始或2.另一种添加或删除(和编辑)属性的方法(参见我可能会根据一些逻辑编辑描述)或3找到孔在我的代码中,我可以找到并编辑可浏览的(描述和显示名称)。



更新上面的第二个链接 http://social.msdn.microsoft.com/论坛/ en-US / adodotnetentityframework / thread / 617ebfca-0f68-4b90-83fd-0da758fadbd0 / ,有很多我需要的,我想。将属性数组变量添加到类中,然后添加一些代码来查看是否设置了这些变量似乎具有我正在寻找的效果。但是请留下一个更好的答案。

  partial class Client:ICustomTypeDescriptor 
{
public Attribute [] SignOutAttributes; //添加此

#region ICustomTypeDescriptor成员

... //查看其他代码的链接

public PropertyDescriptorCollection GetProperties(Attribute [ ]属性)
{
var propsColl = TypeDescriptor.GetProperties(this,attributes,true);
var props = new List< PropertyDescriptor> ();
foreach(PropertyDescriptor prop in propsColl)
{
String strUPPERCaseName = prop.Name.ToUpper(); //对于我的厚手指
//确保大小写的值为
switch(strUPPERCaseName)
{
caseSIGNOUTAFTER:
if(SignOutAttributes!= null)
{
props.Add(new CustomPropertyDescriptor(prop,SignOutAttributes));
}
else
{
props.Add(new CustomPropertyDescriptor(prop,new Attribute []
{
new CategoryAttribute(Settings),
new DisplayNameAttribute(Signout After),
new BrowsableAttribute(true),
new ReadOnlyAttribute(false)
}));
}
break;
默认值:
props.Add(prop);
break;
}
}
return new PropertyDescriptorCollection(props.ToArray());
}

在我的代码中,我可以更改属性数组以具有我想要的属性值。

  _client.SignOutAttributes = new Attribute [] 
{
new CategoryAttribute(My Category) ,
new DisplayNameAttribute(Signout After),
new BrowsableAttribute(true),
new ReadOnlyAttribute(false)
};

我对此不满意。我必须为每个属性编写代码。

解决方案

使用 ICustomTypeDescriptor 当您想要动态(在运行时设置)属性时,绝对是一个很好的解决方案。这是一个通用的ICustomTypeDescriptor实用程序类,我一直在使用这种类型的属性网格黑客,很简单:

  public sealed class DynamicTypeDescriptor:ICustomTypeDescriptor,INotifyPropertyChanged 
{
private Type _type;
private AttributeCollection _attributes;
private TypeConverter _typeConverter;
私人字典< Type,object> _editors;
private EventDescriptor _defaultEvent;
private PropertyDescriptor _defaultProperty;
private EventDescriptorCollection _events;

public event PropertyChangedEventHandler PropertyChanged;

private DynamicTypeDescriptor()
{
}

public DynamicTypeDescriptor(Type type)
{
if(type == null)
throw new ArgumentNullException(type);

_type = type;
_typeConverter = TypeDescriptor.GetConverter(type);
_defaultEvent = TypeDescriptor.GetDefaultEvent(type);
_defaultProperty = TypeDescriptor.GetDefaultProperty(type);
_events = TypeDescriptor.GetEvents(type);

列表< PropertyDescriptor> normalProperties = new List< PropertyDescriptor>();
OriginalProperties = TypeDescriptor.GetProperties(type);
foreach(OriginalProperties中的PropertyDescriptor属性)
{
if(!property.IsBrowsable)
continue;

normalProperties.Add(property);

}
属性= new PropertyDescriptorCollection(normalProperties.ToArray());

_attributes = TypeDescriptor.GetAttributes(type);

_editors = new Dictionary< Type,object>();
对象编辑器= TypeDescriptor.GetEditor(type,typeof(UITypeEditor));
if(editor!= null)
{
_editors.Add(typeof(UITypeEditor),editor);
}
editor = TypeDescriptor.GetEditor(type,typeof(ComponentEditor));
if(editor!= null)
{
_editors.Add(typeof(ComponentEditor),editor);
}
editor = TypeDescriptor.GetEditor(type,typeof(InstanceCreationEditor));
if(editor!= null)
{
_editors.Add(typeof(InstanceCreationEditor),editor);
}
}

public T GetPropertyValue< T>(string name,T defaultValue)
{
if(name == null)
抛出新的ArgumentNullException(name);

foreach(属性中的PropertyDescriptor pd)
{
if(pd.Name == name)
{
try
{
return(T)Convert.ChangeType(pd.GetValue(Component),typeof(T));
}
catch
{
return defaultValue;
}
}
}
return defaultValue;


public void SetPropertyValue(string name,object value)
{
if(name == null)
throw new ArgumentNullException(name );

foreach(属性中的PropertyDescriptor pd)
{
if(pd.Name == name)
{
pd.SetValue(Component,value) ;
break;
}
}
}

内部void OnValueChanged(PropertyDescriptor prop)
{
PropertyChangedEventHandler handler = PropertyChanged;
if(handler!= null)
{
handler(this,new PropertyChangedEventArgs(prop.Name));
}
}

内部静态T GetAttribute< T>(AttributeCollection属性)其中T:属性
{
if(attributes == null)
返回null;

foreach(属性中的属性)
{
if(typeof(T).IsAssignableFrom(att.GetType()))
return(T)att;
}
返回null;
}

public sealed class DynamicProperty:PropertyDescriptor,INotifyPropertyChanged
{
private readonly Type _type;
private readonly bool _hasDefaultValue;
私有readonly对象_defaultValue;
private readonly PropertyDescriptor _existing;
private readonly DynamicTypeDescriptor _descriptor;
私人字典< Type,object> _editors;
私人bool? _只读;
私人bool? _browsable;
私人字符串_displayName;
私人字符串_description;
private string _category;
私人列表<属性> _attributes = new List< Attribute>();

public event PropertyChangedEventHandler PropertyChanged;

内部DynamicProperty(DynamicTypeDescriptor描述符,类型类型,对象值,字符串名称,属性[] attrs)
:base(name,attrs)
{
_descriptor =描述;
_type = type;
Value = value;
DefaultValueAttribute def = DynamicTypeDescriptor.GetAttribute< DefaultValueAttribute>(Attributes);
if(def == null)
{
_hasDefaultValue = false;
}
else
{
_hasDefaultValue = true;
_defaultValue = def.Value;
}
if(attrs!= null)
{
foreach(attrs中的属性att)
{
_attributes.Add(att);
}
}
}

内部静态属性[] GetAttributes(PropertyDescriptor exists)
{
列表&&属性> atts = new List< Attribute>();
foreach(Attribute a in existing.Attributes)
{
atts.Add(a);
}
return atts.ToArray();


内部DynamicProperty(DynamicTypeDescriptor描述符,PropertyDescriptor现有的对象组件)
:this(descriptor,existing.PropertyType,existing.GetValue(component),existing.Name,GetAttributes (现有))
{
_existing = existing;
}

public void RemoveAttributesOfType< T>()其中T:属性
{
列表&<属性> remove = new List&Attribute>();
foreach(Attribute att in _attributes)
{
if(typeof(T).IsAssignableFrom(att.GetType()))
{
remove.Add );
}
}

foreach(删除中的属性att)
{
_attributes.Remove(att);
}
}

public IList&Attribute> AttributesList
{
get
{
return _attributes;
}
}

public override AttributeCollection属性
{
get
{
返回新的AttributeCollection(_attributes.ToArray() );
}
}

public object Value {get;组;

public override bool CanResetValue(object component)
{
if(_existing!= null)
return _existing.CanResetValue(component);

return _hasDefaultValue;
}

public override Type ComponentType
{
get
{
if(_existing!= null)
return _existing。 COMPONENTTYPE;

return typeof(object);
}
}

public override object GetValue(object component)
{
if(_existing!= null)
return _existing.GetValue (零件);

返回值;
}

public override string类别
{
get
{
if(_category!= null)
return _category;

return base.Category;
}
}

public void SetCategory(string category)
{
_category = category;
}

public override string描述
{
get
{
if(_description!= null)
return _description;

return base.Description;
}
}

public void SetDescription(string description)
{
_description = description;
}

public override string DisplayName
{
get
{
if(_displayName!= null)
return _displayName;

if(_existing!= null)
return _existing.DisplayName;

return base.DisplayName;
}
}

public void SetDisplayName(string displayName)
{
_displayName = displayName;
}

public override bool IsBrowsable
{
get
{
if(_browsable.HasValue)
return _browsable.Value ;

return base.IsBrowsable;
}
}

public void SetBrowsable(bool browableable)
{
_browsable =可浏览;
}

public override bool IsReadOnly
{
get
{
if(_readOnly.HasValue)
return _readOnly.Value ;

if(_existing!= null)
return _existing.IsReadOnly;

ReadOnlyAttribute att = DynamicTypeDescriptor.GetAttribute< ReadOnlyAttribute>(Attributes);
if(att == null)
return false;

return att.IsReadOnly;
}
}

public void SetIsReadOnly(bool readOnly)
{
_readOnly = readOnly;
}

public override Type PropertyType
{
get
{
if(_existing!= null)
return _existing。财产种类;

return _type;
}
}

public override void ResetValue(object component)
{
if(_existing!= null)
{
_existing.ResetValue(component);
PropertyChangedEventHandler handler = PropertyChanged;
if(handler!= null)
{
handler(this,new PropertyChangedEventArgs(Name));
}
_descriptor.OnValueChanged(this);
return;
}

if(CanResetValue(component))
{
Value = _defaultValue;
_descriptor.OnValueChanged(this);
}
}

public override void SetValue(object component,object value)
{
if(_existing!= null)
{
_existing.SetValue(component,value);
PropertyChangedEventHandler handler = PropertyChanged;
if(handler!= null)
{
handler(this,new PropertyChangedEventArgs(Name));
}
_descriptor.OnValueChanged(this);
return;
}

Value = value;
_descriptor.OnValueChanged(this);


public override bool ShouldSerializeValue(object component)
{
if(_existing!= null)
return _existing.ShouldSerializeValue(component);

返回false;


public override object GetEditor(Type editorBaseType)
{
if(editorBaseType == null)
throw new ArgumentNullException(editorBaseType);

if(_editors!= null)
{
对象类型;
if((_editors.TryGetValue(editorBaseType,out type))&&(type!= null))
返回类型;
}
return base.GetEditor(editorBaseType);
$ b public void SetEditor(Type editorBaseType,object obj)
{
if(editorBaseType == null)
throw new ArgumentNullException(editorBaseType );

if(_editors == null)
{
if(obj == null)
return;

_editors = new Dictionary< Type,object>();
}
if(obj == null)
{
_editors.Remove(editorBaseType);
}
else
{
_editors [editorBaseType] = obj;


$ b public PropertyDescriptor AddProperty(Type type,string name,object value,string displayName,string description,string category,bool hasDefaultValue,object defaultValue ,bool readOnly)
{
return AddProperty(type,name,value,displayName,description,category,hasDefaultValue,defaultValue,readOnly,null);


public PropertyDescriptor AddProperty(
类型,
字符串名称,
对象值,
字符串displayName,
字符串描述,
字符串类别,
bool hasDefaultValue,
对象defaultValue,
bool readOnly,
类型uiTypeEditor
{
if(type = = null)
throw new ArgumentNullException(type);

if(name == null)
throw new ArgumentNullException(name);

列表<属性> atts = new List< Attribute>();
if(!string.IsNullOrEmpty(displayName))
{
atts.Add(new DisplayNameAttribute(displayName));
}

if(!string.IsNullOrEmpty(description))
{
atts.Add(new DescriptionAttribute(description));
}

if(!string.IsNullOrEmpty(category))
{
atts.Add(new CategoryAttribute(category));
}

if(hasDefaultValue)
{
atts.Add(new DefaultValueAttribute(defaultValue));
}

if(uiTypeEditor!= null)
{
atts.Add(new EditorAttribute(uiTypeEditor,typeof(UITypeEditor)));
}

if(readOnly)
{
atts.Add(new ReadOnlyAttribute(true));
}

DynamicProperty属性= new DynamicProperty(this,type,value,name,atts.ToArray());
AddProperty(property);
返回属性;


public void RemoveProperty(string name)
{
if(name == null)
throw new ArgumentNullException(name);

列表< PropertyDescriptor> remove = new List< PropertyDescriptor>();
foreach(属性中的PropertyDescriptor pd)
{
if(pd.Name == name)
{
remove.Add(pd);
}
}

foreach(删除中的PropertyDescriptor pd)
{
Properties.Remove(pd);
}
}

public void AddProperty(PropertyDescriptor属性)
{
if(property == null)
throw new ArgumentNullException(属性);

Properties.Add(property);
}

public override string ToString()
{
return base.ToString()+(+ Component +);
}

public PropertyDescriptorCollection OriginalProperties {get;私人集合}
public PropertyDescriptorCollection属性{get;私人集合

public DynamicTypeDescriptor FromComponent(object component)
{
if(component == null)
throw new ArgumentNullException(component);

if(!_type.IsAssignableFrom(component.GetType()))
throw new ArgumentException(null,component);

DynamicTypeDescriptor desc = new DynamicTypeDescriptor();
desc._type = _type;
desc.Component = component;

//目的浅浅拷贝
desc._typeConverter = _typeConverter;
desc._editors = _editors;
desc._defaultEvent = _defaultEvent;
desc._defaultProperty = _defaultProperty;
desc._attributes = _attributes;
desc._events = _events;
desc.OriginalProperties = OriginalProperties;

//跟踪值
列表< PropertyDescriptor> properties = new List< PropertyDescriptor>();
foreach(属性中的PropertyDescriptor pd)
{
DynamicProperty ap = new DynamicProperty(desc,pd,component);
properties.Add(ap);
}

desc.Properties = new PropertyDescriptorCollection(properties.ToArray());
return desc;
}

public object Component {get;私人集合}
public string ClassName {get;组; }
public string ComponentName {get;组; }

AttributeCollection ICustomTypeDescriptor.GetAttributes()
{
return _attributes;
}

string ICustomTypeDescriptor.GetClassName()
{
if(ClassName!= null)
return ClassName;

if(Component!= null)
return Component.GetType()。Name;

if(_type!= null)
return _type.Name;

返回null;
}

string ICustomTypeDescriptor.GetComponentName()
{
if(ComponentName!= null)
return ComponentName;

return Component!= null? Component.ToString():null;
}

TypeConverter ICustomTypeDescriptor.GetConverter()
{
return _typeConverter;
}

EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
{
return _defaultEvent;
}

PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
{
return _defaultProperty;
}

对象ICustomTypeDescriptor.GetEditor(类型editorBaseType)
{
对象编辑器;
if(_editors.TryGetValue(editorBaseType,out editor))
return editor;

返回null;
}

EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute [] attributes)
{
return _events;
}

EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
{
return _events;
}

PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute [] attributes)
{
return属性;
}

PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
{
return属性;
}

对象ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
{
return Component;
}
}


Trying to remove or place items on a property grid by changing the Browsable attribute.

But unless browsable is set on object creation my code to change Browsable doesn't work. Now I can manually add browsable, but when I make a change to my entity (still developing project so lots of changes to entity) any additional attributes I add go away.

I attempted to set [Browsable(true)] two ways other ways: http://ardalis.com/adding-attributes-to-generated-classes and http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/617ebfca-0f68-4b90-83fd-0da758fadbd0/

Both seem to actually set the Browsable correctly, but when I loop thru the Attributes in Property Descriptor it is not there (for me to change).

  String fieldname = "browsable"; // I also edit "description"
  PropertyDescriptor pd = TypeDescriptor.GetProperties(o.GetType())[propertyName];
  object attrib = null;
  AttributeCollection attribs = pd.Attributes;

  foreach (Attribute a in attribs)
    {
    if (a.GetType() == attributeType)
      {
      attrib = a;
      break;
      }
    }
// The microsoft documentation leads one to believe the following line of code would find the desired attribute,
// negating the need for the more complete foreach statement above.
// However,  it appears to find attribute even when it does not exist. Setting value for "found" attribute 
// will result in random memory being changed, which results in very unpredictable behavior.
// attrib = pd.Attributes[t];

if (attrib != null)
  {
  // locate field that contains value 
  FieldInfo field = attrib.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
  if (field != null)
    {
    if (field.FieldType == value.GetType())
      {
      // set field to desired value
      field.SetValue(attrib, value);
      }
    }
    }
  else
    {
    throw new Exception("Attribute (" + attributeType.Name + ") does not exist for Property(" + propertyName + ")");
    }

So I keep getting the Exception that I throw if it doesn't find "browsable" - but only if not set in Model.Designer.cs first.

Below is what my Model.Designer.cs looks like.

  /// <summary>
  /// No Metadata Documentation available.
  /// </summary>
  [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=true)]
  [DataMemberAttribute()]
  [Browsable(false)] // this works, but goes away if change my entity
  public Nullable<global::System.TimeSpan> SignoutAfter
    {
    get
      {
      return _SignoutAfter;
      }
    set
      {
      OnSignoutAfterChanging(value);
      ReportPropertyChanging("SignoutAfter");
      _SignoutAfter = StructuralObject.SetValidValue(value);
      ReportPropertyChanged("SignoutAfter");
      OnSignoutAfterChanged();
      }
    }
  private Nullable<global::System.TimeSpan> _SignoutAfter;
  partial void OnSignoutAfterChanging(Nullable<global::System.TimeSpan> value);
  partial void OnSignoutAfterChanged();

So I need a way to either 1. add browsable to entity when I edit them so it is always on perhaps editing the t4, but I don't even know where to begin with that or 2. Another way to add or remove (and edit) the properties (see I might edit the description based on some logic) or 3 find the hole in my code so I can find and edit browsable (description and displayname).

Update The second link above, http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/617ebfca-0f68-4b90-83fd-0da758fadbd0/ , has a lot of what I need, I think. Adding a Attribute array variable to the class and some code to see if that is set seems to have the effect that I am looking for. But leaving this open to find a better answer.

partial class Client : ICustomTypeDescriptor
  {
   public Attribute[] SignOutAttributes; // added this

   #region ICustomTypeDescriptor Members

   ... // see the link for the other code

   public PropertyDescriptorCollection GetProperties (Attribute[] attributes)
      {
      var propsColl = TypeDescriptor.GetProperties (this, attributes, true);
      var props = new List<PropertyDescriptor> ();
      foreach (PropertyDescriptor prop in propsColl)
         {
         String strUPPERCaseName = prop.Name.ToUpper (); // for my thick fingers
         // make sure case values are upper case 
         switch (strUPPERCaseName)
            {
            case "SIGNOUTAFTER":
               if (SignOutAttributes != null)
                  {
                  props.Add(new CustomPropertyDescriptor(prop, SignOutAttributes));
                  }
                else
                  {
                   props.Add (new CustomPropertyDescriptor (prop, new Attribute[]
                     {
                     new CategoryAttribute("Settings"),
                     new DisplayNameAttribute("Signout After"),
                     new BrowsableAttribute(true),
                     new ReadOnlyAttribute(false)
                     }));
                  }
                break;
            default:
               props.Add (prop);
               break;
            }
         }
       return new PropertyDescriptorCollection (props.ToArray ());
       }

In my code I can change the Attribute Array to have what Attribute values I want.

 _client.SignOutAttributes = new Attribute[]
                {
                    new CategoryAttribute ("My Category"),
                    new DisplayNameAttribute("Signout After"),
                    new BrowsableAttribute(true),
                    new ReadOnlyAttribute(false)
                };

I'm not 100% happy with this. I have to write code for each Property.

解决方案

Using ICustomTypeDescriptor is definitely the good solution when you want dynamic (set at runtime) properties. Here is generic ICustomTypeDescriptor utility class that I've been using for this sort of property grid hacking, it's pretty straightforward to use:

public sealed class DynamicTypeDescriptor: ICustomTypeDescriptor, INotifyPropertyChanged
{
    private Type _type;
    private AttributeCollection _attributes;
    private TypeConverter _typeConverter;
    private Dictionary<Type, object> _editors;
    private EventDescriptor _defaultEvent;
    private PropertyDescriptor _defaultProperty;
    private EventDescriptorCollection _events;

    public event PropertyChangedEventHandler PropertyChanged;

    private DynamicTypeDescriptor()
    {
    }

    public DynamicTypeDescriptor(Type type)
    {
        if (type == null)
            throw new ArgumentNullException("type");

        _type = type;
        _typeConverter = TypeDescriptor.GetConverter(type);
        _defaultEvent = TypeDescriptor.GetDefaultEvent(type);
        _defaultProperty = TypeDescriptor.GetDefaultProperty(type);
        _events = TypeDescriptor.GetEvents(type);

        List<PropertyDescriptor> normalProperties = new List<PropertyDescriptor>();
        OriginalProperties = TypeDescriptor.GetProperties(type);
        foreach (PropertyDescriptor property in OriginalProperties)
        {
            if (!property.IsBrowsable)
                continue;

            normalProperties.Add(property);

        }
        Properties = new PropertyDescriptorCollection(normalProperties.ToArray());

        _attributes = TypeDescriptor.GetAttributes(type);

        _editors = new Dictionary<Type, object>();
        object editor = TypeDescriptor.GetEditor(type, typeof(UITypeEditor));
        if (editor != null)
        {
            _editors.Add(typeof(UITypeEditor), editor);
        }
        editor = TypeDescriptor.GetEditor(type, typeof(ComponentEditor));
        if (editor != null)
        {
            _editors.Add(typeof(ComponentEditor), editor);
        }
        editor = TypeDescriptor.GetEditor(type, typeof(InstanceCreationEditor));
        if (editor != null)
        {
            _editors.Add(typeof(InstanceCreationEditor), editor);
        }
    }

    public T GetPropertyValue<T>(string name, T defaultValue)
    {
        if (name == null)
            throw new ArgumentNullException("name");

        foreach (PropertyDescriptor pd in Properties)
        {
            if (pd.Name == name)
            {
                try
                {
                    return (T)Convert.ChangeType(pd.GetValue(Component), typeof(T));
                }
                catch
                {
                    return defaultValue;
                }
            }
        }
        return defaultValue;
    }

    public void SetPropertyValue(string name, object value)
    {
        if (name == null)
            throw new ArgumentNullException("name");

        foreach (PropertyDescriptor pd in Properties)
        {
            if (pd.Name == name)
            {
                pd.SetValue(Component, value);
                break;
            }
        }
    }

    internal void OnValueChanged(PropertyDescriptor prop)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(prop.Name));
        }
    }

    internal static T GetAttribute<T>(AttributeCollection attributes) where T : Attribute
    {
        if (attributes == null)
            return null;

        foreach (Attribute att in attributes)
        {
            if (typeof(T).IsAssignableFrom(att.GetType()))
                return (T)att;
        }
        return null;
    }

    public sealed class DynamicProperty: PropertyDescriptor, INotifyPropertyChanged
    {
        private readonly Type _type;
        private readonly bool _hasDefaultValue;
        private readonly object _defaultValue;
        private readonly PropertyDescriptor _existing;
        private readonly DynamicTypeDescriptor _descriptor;
        private Dictionary<Type, object> _editors;
        private bool? _readOnly;
        private bool? _browsable;
        private string _displayName;
        private string _description;
        private string _category;
        private List<Attribute> _attributes = new List<Attribute>();

        public event PropertyChangedEventHandler PropertyChanged;

        internal DynamicProperty(DynamicTypeDescriptor descriptor, Type type, object value, string name, Attribute[] attrs)
            : base(name, attrs)
        {
            _descriptor = descriptor;
            _type = type;
            Value = value;
            DefaultValueAttribute def = DynamicTypeDescriptor.GetAttribute<DefaultValueAttribute>(Attributes);
            if (def == null)
            {
                _hasDefaultValue = false;
            }
            else
            {
                _hasDefaultValue = true;
                _defaultValue = def.Value;
            }
            if (attrs != null)
            {
                foreach (Attribute att in attrs)
                {
                    _attributes.Add(att);
                }
            }
        }

        internal static Attribute[] GetAttributes(PropertyDescriptor existing)
        {
            List<Attribute> atts = new List<Attribute>();
            foreach (Attribute a in existing.Attributes)
            {
                atts.Add(a);
            }
            return atts.ToArray();
        }

        internal DynamicProperty(DynamicTypeDescriptor descriptor, PropertyDescriptor existing, object component)
            : this(descriptor, existing.PropertyType, existing.GetValue(component), existing.Name, GetAttributes(existing))
        {
            _existing = existing;
        }

        public void RemoveAttributesOfType<T>() where T : Attribute
        {
            List<Attribute> remove = new List<Attribute>();
            foreach (Attribute att in _attributes)
            {
                if (typeof(T).IsAssignableFrom(att.GetType()))
                {
                    remove.Add(att);
                }
            }

            foreach (Attribute att in remove)
            {
                _attributes.Remove(att);
            }
        }

        public IList<Attribute> AttributesList
        {
            get
            {
                return _attributes;
            }
        }

        public override AttributeCollection Attributes
        {
            get
            {
                return new AttributeCollection(_attributes.ToArray());
            }
        }

        public object Value { get; set; }

        public override bool CanResetValue(object component)
        {
            if (_existing != null)
                return _existing.CanResetValue(component);

            return _hasDefaultValue;
        }

        public override Type ComponentType
        {
            get
            {
                if (_existing != null)
                    return _existing.ComponentType;

                return typeof(object);
            }
        }

        public override object GetValue(object component)
        {
            if (_existing != null)
                return _existing.GetValue(component);

            return Value;
        }

        public override string Category
        {
            get
            {
                if (_category != null)
                    return _category;

                return base.Category;
            }
        }

        public void SetCategory(string category)
        {
            _category = category;
        }

        public override string Description
        {
            get
            {
                if (_description != null)
                    return _description;

                return base.Description;
            }
        }

        public void SetDescription(string description)
        {
            _description = description;
        }

        public override string DisplayName
        {
            get
            {
                if (_displayName != null)
                    return _displayName;

                if (_existing != null)
                    return _existing.DisplayName;

                return base.DisplayName;
            }
        }

        public void SetDisplayName(string displayName)
        {
            _displayName = displayName;
        }

        public override bool IsBrowsable
        {
            get
            {
                if (_browsable.HasValue)
                    return _browsable.Value;

                return base.IsBrowsable;
            }
        }

        public void SetBrowsable(bool browsable)
        {
            _browsable = browsable;
        }

        public override bool IsReadOnly
        {
            get
            {
                if (_readOnly.HasValue)
                    return _readOnly.Value;

                if (_existing != null)
                    return _existing.IsReadOnly;

                ReadOnlyAttribute att = DynamicTypeDescriptor.GetAttribute<ReadOnlyAttribute>(Attributes);
                if (att == null)
                    return false;

                return att.IsReadOnly;
            }
        }

        public void SetIsReadOnly(bool readOnly)
        {
            _readOnly = readOnly;
        }

        public override Type PropertyType
        {
            get
            {
                if (_existing != null)
                    return _existing.PropertyType;

                return _type;
            }
        }

        public override void ResetValue(object component)
        {
            if (_existing != null)
            {
                _existing.ResetValue(component);
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(Name));
                }
                _descriptor.OnValueChanged(this);
                return;
            }

            if (CanResetValue(component))
            {
                Value = _defaultValue;
                _descriptor.OnValueChanged(this);
            }
        }

        public override void SetValue(object component, object value)
        {
            if (_existing != null)
            {
                _existing.SetValue(component, value);
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(Name));
                }
                _descriptor.OnValueChanged(this);
                return;
            }

            Value = value;
            _descriptor.OnValueChanged(this);
        }

        public override bool ShouldSerializeValue(object component)
        {
            if (_existing != null)
                return _existing.ShouldSerializeValue(component);

            return false;
        }

        public override object GetEditor(Type editorBaseType)
        {
            if (editorBaseType == null)
                throw new ArgumentNullException("editorBaseType");

            if (_editors != null)
            {
                object type;
                if ((_editors.TryGetValue(editorBaseType, out type)) && (type != null))
                    return type;
            }
            return base.GetEditor(editorBaseType);
        }

        public void SetEditor(Type editorBaseType, object obj)
        {
            if (editorBaseType == null)
                throw new ArgumentNullException("editorBaseType");

            if (_editors == null)
            {
                if (obj == null)
                    return;

                _editors = new Dictionary<Type, object>();
            }
            if (obj == null)
            {
                _editors.Remove(editorBaseType);
            }
            else
            {
                _editors[editorBaseType] = obj;
            }
        }
    }

    public PropertyDescriptor AddProperty(Type type, string name, object value, string displayName, string description, string category, bool hasDefaultValue, object defaultValue, bool readOnly)
    {
        return AddProperty(type, name, value, displayName, description, category, hasDefaultValue, defaultValue, readOnly, null);
    }

    public PropertyDescriptor AddProperty(
        Type type,
        string name,
        object value,
        string displayName,
        string description,
        string category,
        bool hasDefaultValue,
        object defaultValue,
        bool readOnly,
        Type uiTypeEditor)
    {
        if (type == null)
            throw new ArgumentNullException("type");

        if (name == null)
            throw new ArgumentNullException("name");

        List<Attribute> atts = new List<Attribute>();
        if (!string.IsNullOrEmpty(displayName))
        {
            atts.Add(new DisplayNameAttribute(displayName));
        }

        if (!string.IsNullOrEmpty(description))
        {
            atts.Add(new DescriptionAttribute(description));
        }

        if (!string.IsNullOrEmpty(category))
        {
            atts.Add(new CategoryAttribute(category));
        }

        if (hasDefaultValue)
        {
            atts.Add(new DefaultValueAttribute(defaultValue));
        }

        if (uiTypeEditor != null)
        {
            atts.Add(new EditorAttribute(uiTypeEditor, typeof(UITypeEditor)));
        }

        if (readOnly)
        {
            atts.Add(new ReadOnlyAttribute(true));
        }

        DynamicProperty property = new DynamicProperty(this, type, value, name, atts.ToArray());
        AddProperty(property);
        return property;
    }

    public void RemoveProperty(string name)
    {
        if (name == null)
            throw new ArgumentNullException("name");

        List<PropertyDescriptor> remove = new List<PropertyDescriptor>();
        foreach (PropertyDescriptor pd in Properties)
        {
            if (pd.Name == name)
            {
                remove.Add(pd);
            }
        }

        foreach (PropertyDescriptor pd in remove)
        {
            Properties.Remove(pd);
        }
    }

    public void AddProperty(PropertyDescriptor property)
    {
        if (property == null)
            throw new ArgumentNullException("property");

        Properties.Add(property);
    }

    public override string ToString()
    {
        return base.ToString() + " (" + Component + ")";
    }

    public PropertyDescriptorCollection OriginalProperties { get; private set; }
    public PropertyDescriptorCollection Properties { get; private set; }

    public DynamicTypeDescriptor FromComponent(object component)
    {
        if (component == null)
            throw new ArgumentNullException("component");

        if (!_type.IsAssignableFrom(component.GetType()))
            throw new ArgumentException(null, "component");

        DynamicTypeDescriptor desc = new DynamicTypeDescriptor();
        desc._type = _type;
        desc.Component = component;

        // shallow copy on purpose
        desc._typeConverter = _typeConverter;
        desc._editors = _editors;
        desc._defaultEvent = _defaultEvent;
        desc._defaultProperty = _defaultProperty;
        desc._attributes = _attributes;
        desc._events = _events;
        desc.OriginalProperties = OriginalProperties;

        // track values
        List<PropertyDescriptor> properties = new List<PropertyDescriptor>();
        foreach (PropertyDescriptor pd in Properties)
        {
            DynamicProperty ap = new DynamicProperty(desc, pd, component);
            properties.Add(ap);
        }

        desc.Properties = new PropertyDescriptorCollection(properties.ToArray());
        return desc;
    }

    public object Component { get; private set; }
    public string ClassName { get; set; }
    public string ComponentName { get; set; }

    AttributeCollection ICustomTypeDescriptor.GetAttributes()
    {
        return _attributes;
    }

    string ICustomTypeDescriptor.GetClassName()
    {
        if (ClassName != null)
            return ClassName;

        if (Component != null)
            return Component.GetType().Name;

        if (_type != null)
            return _type.Name;

        return null;
    }

    string ICustomTypeDescriptor.GetComponentName()
    {
        if (ComponentName != null)
            return ComponentName;

        return Component != null ? Component.ToString() : null;
    }

    TypeConverter ICustomTypeDescriptor.GetConverter()
    {
        return _typeConverter;
    }

    EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
    {
        return _defaultEvent;
    }

    PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
    {
        return _defaultProperty;
    }

    object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
    {
        object editor;
        if (_editors.TryGetValue(editorBaseType, out editor))
            return editor;

        return null;
    }

    EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
    {
        return _events;
    }

    EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
    {
        return _events;
    }

    PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
    {
        return Properties;
    }

    PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
    {
        return Properties;
    }

    object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
    {
        return Component;
    }
}

这篇关于PropertyGrid可浏览未找到实体框架创建的属性,如何找到它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆