C# 設計時動態改變實體在PropertyGrid中顯示出來的屬性

衣舞晨風發表於2015-11-21

方法一:

    /// <summary>
    /// 實體屬性處理
    /// </summary>
    public class PropertyHandle
    {
        #region 反射控制只讀、可見屬性
        //SetPropertyVisibility(obj,   "名稱 ",   true); 
        //obj指的就是你的SelectObject,   “名稱”是你SelectObject的一個屬性 
        //當然,呼叫這兩個方法後,重新SelectObject一下,就可以了。
        /// <summary>
        /// 通過反射控制屬性是否只讀
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="propertyName"></param>
        /// <param name="readOnly"></param>
        public static void SetPropertyReadOnly(object obj, string propertyName, bool readOnly)
        {
            Type type = typeof(ReadOnlyAttribute);
            PropertyDescriptorCollection props = TypeDescriptor.GetProperties(obj);
            AttributeCollection attrs = props[propertyName].Attributes;
            FieldInfo fld = type.GetField("isReadOnly", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.CreateInstance);
            fld.SetValue(attrs[type], readOnly);
        }

        /// <summary>
        /// 通過反射控制屬性是否可見
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="propertyName"></param>
        /// <param name="visible"></param>
        public static void SetPropertyVisibility(object obj, string propertyName, bool visible)
        {
            Type type = typeof(BrowsableAttribute);
            PropertyDescriptorCollection props = TypeDescriptor.GetProperties(obj);
            AttributeCollection attrs = props[propertyName].Attributes;
            FieldInfo fld = type.GetField("browsable", BindingFlags.Instance | BindingFlags.NonPublic);
            fld.SetValue(attrs[type], visible);
        }
        #endregion
    }
舉例:比如某個實體類TestEntity中有自增列(IdentityColumnInfo)這麼一個屬性,該自增列對應的實體類如下:

public class IdentityColumnEntity 
    {
        private bool isIncrementColumn;
        /// <summary>
        /// 是否是自增列
        /// </summary>
        [Browsable(true)]
        [Category("基本")]
        [DisplayName("是否是自增列")]
        [ReadOnly(false)]
        [DefaultValue(false)]
        public bool IsIncrementColumn
        {
            set { isIncrementColumn = value; }
            get { return isIncrementColumn; }
        }

        private Int64 identityIncrement;
        /// <summary>
        /// 標識增量
        /// </summary>
        [Browsable(true)]
        [Category("基本")]
        [DisplayName("標識增量")]
        [ReadOnly(false)]
        [Description("標識增量屬性指定在 Microsoft SQL Server 為插入的行生成標識值時,在現有的最大行標識值基礎上所加的值。標識增量必須是 非零 整數,位數等於或小於 10。")]
        public Int64 IdentityIncrement
        {
            set { identityIncrement = value; }
            get { return identityIncrement; }
        }

        private Int64 ident_Seed;
        /// <summary>
        /// 標識種子 
        /// </summary>
        [Browsable(true)]
        [Category("基本")]
        [DisplayName("標識種子")]
        [ReadOnly(false)]
        [Description("指示標識列的初始行值。標識種子必須是  整數,位數等於或小於 10。")]
        public Int64 Ident_Seed
        {
            set { ident_Seed = value; }
            get { return ident_Seed; }
        }       
    }
實體類TestEntity程式碼如下:

  public class TestEntity
    {
        private IdentityColumnEntity identityColumnInfo;
        /// <summary>
        /// 是否自增列
        /// </summary>
        [Category("擴充套件資訊")]
        [DisplayName("自增列資訊")]
        [ReadOnlyAttribute(true)]
        [XmlIgnore]
        [Browsable(true)]
        //[XmlAttribute]
        public IdentityColumnEntity IdentityColumnInfo
        {
            get
            {
                if (identityColumnInfo != null && identityColumnInfo.IsIncrementColumn)
                {
                    PropertyHandle.SetPropertyReadOnly(identityColumnInfo, "Ident_Seed", true);
                    PropertyHandle.SetPropertyReadOnly(identityColumnInfo, "IdentityIncrement", true);
                    PropertyHandle.SetPropertyReadOnly(identityColumnInfo, "IsIncrementColumn", true);
                    PropertyHandle.SetPropertyReadOnly(this, "IsInsert", true);
                    PropertyHandle.SetPropertyReadOnly(this, "IsUpdate", true);
                }
                return identityColumnInfo;
            }
            set
            {
                identityColumnInfo = value;
            }
        }

        /// <summary>
        /// 是否插入
        /// </summary>
        [Category("維護資訊")]
        [DisplayName("是否插入")]
        [ReadOnlyAttribute(false)]
        [XmlAttribute]
        public bool IsInsert
        {
            get
            ;
            set
            ;
        }

        /// <summary>
        /// 是否更新
        /// </summary>
        [Category("維護資訊")]
        [DisplayName("是否更新")]
        [ReadOnlyAttribute(false)]
        [XmlAttribute]
        public bool IsUpdate
        {
            get
            ;
            set
            ;
        }
    }
通過 PropertyHandle.SetPropertyReadOnly即可實現,效果如下:


演示原始碼:點選開啟連結

本文參考: 如何在設計時中動態改變控制元件屬性在PropertyGrid中顯示出來的只讀性

小注:

如何修改自定義屬性的顯示問題呢?


方法二:即參考文章中提到的:Unleash PropertyGrid with Dynamic Properties and Globalization

原始碼及演示demo下載:點選開啟連結






相關文章