C# 动态设置PropertyGrid中属性的只读属性
我有一个C# 动态设置PropertyGrid中属性的只读属性,c#,.net,winforms,readonly,propertygrid,C#,.net,Winforms,Readonly,Propertygrid,我有一个PropertyGrid,用于在助手类中显示属性。我将helper类分配给PropertyGrid,如下所示: myPropertyGrid.SelectedObject = mySettingsHelper; [DisplayName("DisplayExA"), Description("DescriptionExA"), ReadOnlyAttribute(true)] public string PropertyA { get; set; } [DisplayName("Di
PropertyGrid
,用于在助手类中显示属性。我将helper类分配给PropertyGrid
,如下所示:
myPropertyGrid.SelectedObject = mySettingsHelper;
[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; }
在helper类中,我在设计时指定ReadOnlyAttribute
,如下所示:
myPropertyGrid.SelectedObject = mySettingsHelper;
[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 { }
}
}
使用反射获取
ReadOnlyAttribute
类的实例引用,然后在该实例上切换IsReadOnly
属性。最后,如果需要,请在PropertyGrid中重新选择该项,将其SelectedObject设置为null,然后将其重置。我不确定,您也可以使用PropertyGridRefreshTabs
方法来实现这一点
编辑:
不幸的是IsReadOnly属性本身是只读的。。。在这种情况下,我们必须使用反射来更改IsReadOnly属性的backing字段的值。使用本文中的库,我完全能够完成我需要的操作(只读属性的对象级分配)。很好的一点是,它允许我仍然使用.NET
PropertyGrid
,并且只使用自定义属性来处理动态设置 添加只读
TextBoxID.Attributes.Add("readonly","true");
删除只读
TextBoxID.Attributes.Remove("readonly");
动态设置PropertyGrid中属性的可浏览或只读属性通常需要一起使用,而且它们也是类似的工作 经过几次接触后,Reza Aghaeiabout“”的伟大答案也适用于操作readonly属性
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());
}
}
您在应用程序中使用了多少
PropertyGrid
?我认为如果一次只使用1个PropertyGrid
,您的目的是可以实现的,我们仍然需要更改type的属性
,但是在选择对象之前,我们会相应地切换ReadOnly
,这应该可以实现。CodeProject文章的死链接。