【问题标题】:Dynamically set readonly attribute of properties in a PropertyGrid在 PropertyGrid 中动态设置属性的只读属性
【发布时间】:2013-10-28 17:03:53
【问题描述】:

我有一个PropertyGrid,用于在帮助类中显示属性。我将助手类分配给PropertyGrid,如下所示:

myPropertyGrid.SelectedObject = mySettingsHelper;

在助手类中,我在设计时分配ReadOnlyAttribute,如下所示:

[DisplayName("DisplayExA"),
Description("DescriptionExA"),
ReadOnlyAttribute(true)]
public string PropertyA { get; set; }

[DisplayName("DisplayExB"),
Description("DescriptionExB"),
ReadOnlyAttribute(false)]
public string PropertyB { get; set; }

[DisplayName("DisplayExC"),
Description("DescriptionExC"),
ReadOnlyAttribute(true)]
public string PropertyC { get; set; }

但现在我需要能够在运行时动态更改单个属性的此属性。根据某些标准,其中一些属性可能需要只读或非只读。如何在运行时动态进行更改?

编辑:

我尝试了以下代码,但这会为对象的每个实例设置 ReadOnly 属性!我想按对象做。有时,一个对象的 PropertyA 可能是只读的,而第二个对象的 PropertyA 可能不是只读的。

public static class PropertyReadOnlyHelper
{
    public static  void SetReadOnly(object container, string name, bool value)
    {
        try
        {
            PropertyDescriptor descriptor = TypeDescriptor.GetProperties(container.GetType())[name];
            ReadOnlyAttribute attribute = (ReadOnlyAttribute)descriptor.Attributes[typeof(ReadOnlyAttribute)];
            FieldInfo fieldToChange = attribute.GetType().GetField("isReadOnly",
                                                System.Reflection.BindingFlags.NonPublic |
                                                System.Reflection.BindingFlags.Instance);
            fieldToChange.SetValue(attribute, value);
        }
        catch { }
    }
}

【问题讨论】:

  • 您在应用程序中使用了多少个PropertyGrid?我认为如果一次只使用 1 个 PropertyGrid 就可以实现您的目的,我们仍然需要更改 Attribute 的类型,但在选择对象之前,我们将相应地切换 ReadOnly 并且应该这样做把戏。

标签: c# .net winforms readonly propertygrid


【解决方案1】:

使用这篇CodeProject 文章中的库,我能够完全满足我的需要(只读属性的对象级分配)。好的是它使我仍然可以使用 .NET PropertyGrid 并且只使用自定义属性来处理动态设置。

【讨论】:

  • CodeProject 文章的死链接。
【解决方案2】:

使用反射获取ReadOnlyAttribute 类的实例引用,然后切换该实例上的IsReadOnly 属性。最后,如果需要,通过将其 SelectedObjects 设置为 null 然后重新设置它来重新选择 PropertyGrid 中的项目。您也可以使用 PropertyGrid RefreshTabs 方法来执行此操作,我不确定。

编辑:

不幸的是 IsReadOnly 属性本身是只读的……在这种情况下,我们必须使用反射来更改 IsReadOnly 属性的支持字段的值。

【讨论】:

    【解决方案3】:

    添加只读

    TextBoxID.Attributes.Add("readonly","true");
    

    删除只读

    TextBoxID.Attributes.Remove("readonly");
    

    【讨论】:

      【解决方案4】:

      在 PropertyGrid 中动态设置属性的 browsablereadonly 属性通常需要一起使用,而且它们是相似的工作

      经过几次接触,Reza Aghaei关于“Hide some properties in PropertyGrid at run-time”的精彩回答也适用于操作只读属性。

      public class CustomObjectWrapper : CustomTypeDescriptor
      {
          public object WrappedObject { get; private set; }
          public List<string> BrowsableProperties { get; private set; }
          public List<string> ReadonlyProperties { get; private set; }
      
          public CustomObjectWrapper(object o)
              : base(TypeDescriptor.GetProvider(o).GetTypeDescriptor(o))
          {
              WrappedObject = o;
              BrowsableProperties = new List<string>() { "Text", "BackColor" };
              ReadonlyProperties = new List<string>() { "Font" };
          }
          public override PropertyDescriptorCollection GetProperties()
          {
              return this.GetProperties(new Attribute[] { });
          }
          public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
          {
              List<PropertyDescriptor> result = new List<PropertyDescriptor>();
      
              IEnumerable<PropertyDescriptor> properties = base.GetProperties(attributes).Cast<PropertyDescriptor>()
                  .Where(p => BrowsableProperties.Contains(p.Name));//unbrowsable filtering
      
              foreach (var p in properties)
              {
                  PropertyDescriptor resultPropertyDescriptor = null;
      
                  //handle being readonly 
                  if (ReadonlyProperties.Contains(p.Name))
                  {
                      List<Attribute> atts = p.Attributes.Cast<Attribute>().ToList();
                      atts.RemoveAll(a => a.GetType().Equals(typeof(ReadOnlyAttribute)));//remove any readonly attribute
                      atts.Add(new ReadOnlyAttribute(true));//add "readonly=true" attribute
      
                      resultPropertyDescriptor = TypeDescriptor.CreateProperty(WrappedObject.GetType(), p, atts.ToArray());
                  }
                  else
                  {
                      resultPropertyDescriptor = TypeDescriptor.CreateProperty(WrappedObject.GetType(), p, p.Attributes.Cast<Attribute>().ToArray());
                  }
      
                  if (resultPropertyDescriptor != null)
                      result.Add(resultPropertyDescriptor);
      
              }
      
              return new PropertyDescriptorCollection(result.ToArray());
          }
      }
      

      及用法:

      propertyGrid1.SelectedObject = new CustomObjectWrapper(myobject);
      

      【讨论】:

        【解决方案5】:
        Please try the code below.
        
        
          
        [CategoryAttribute("2. LINE"), DisplayNameAttribute("Spline Line Tension"),
         DescriptionAttribute("Chart's Spline Line Tension "), ReadOnlyAttribute(false)]
        public float _PG_SplineTension
        {
            get
            {
                bool lbReadyOnly = true;
                SetPropertyReadOnly("_PG_SplineTension", lbReadyOnly);
                return this.cfSplineTension;
           }
            set { this.cfSplineTension = value; }
        }
        
        
        
        private void SetPropertyReadOnly(string lsProperty, bool lbIsReadOnly)
        {
            PropertyDescriptor descriptor = TypeDescriptor.GetProperties(this.GetType())[lsProperty];
            ReadOnlyAttribute attribute = (ReadOnlyAttribute)
        
            descriptor.Attributes[typeof(ReadOnlyAttribute)];
            FieldInfo fieldToChange = attribute.GetType().GetField("isReadOnly",
                System.Reflection.BindingFlags.NonPublic |
                System.Reflection.BindingFlags.Instance);
            fieldToChange.SetValue(attribute, lbIsReadOnly);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-12-05
          • 1970-01-01
          • 2012-05-15
          • 1970-01-01
          • 2023-03-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多