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

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

问题描述

尝试通过更改 Browsable 属性来移除或放置属性网格中的项目.

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.

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

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 + ")");
    }

因此,如果找不到可浏览",我会不断收到我抛出的异常 - 但前提是没有先在 Model.Designer.cs 中设置.

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.

下面是我的 Model.Designer.cs 的样子.

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();

所以我需要一种方法来 1. 在我编辑实体时向实体添加可浏览的内容,因此它可能总是在编辑 t4,但我什至不知道从哪里开始或 2. 另一种添加或删除(并编辑)属性(请参阅我可能会根据某些逻辑编辑描述)或 3 在我的代码中找到漏洞,以便我可以找到并编辑可浏览的(描述和显示名称).

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).

更新上面的第二个链接,http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/617ebfca-0f68-4b90-83fd-0da758fadbd0/ ,有很多我需要什么,我想.将 Attribute 数组变量添加到类和一些代码以查看它是否设置似乎具有我正在寻找的效果.但请保持开放以找到更好的答案.

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)
                };

我对此并不 100% 满意.我必须为每个属性编写代码.

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

推荐答案

使用 ICustomTypeDescriptor当您需要动态(在运行时设置)属性时, 绝对是一个很好的解决方案.这是我一直用于此类属性网格黑客的通用 ICustomTypeDescriptor 实用程序类,使用起来非常简单:

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 Browsable,如何找到它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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