我有一个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 { }
}
}
答案 0 :(得分:1)
我能够使用此CodeProject文章中的库完全按照我的需要(对象级别分配只读属性)。有趣的是它使我仍然可以使用.NET PropertyGrid
并只使用自定义属性来处理动态设置。
答案 1 :(得分:0)
使用反射来获取ReadOnlyAttribute
类的实例引用,然后在该实例上切换IsReadOnly
属性。最后,如果需要,通过将其SelectedObjects设置为null然后重置它,重新选择PropertyGrid中的项。您也许可以使用PropertyGrid RefreshTabs
方法执行此操作,我不确定。
编辑:
不幸的是,IsReadOnly属性本身是只读的...在这种情况下,我们必须使用反射来更改IsReadOnly属性的支持字段的值。
答案 2 :(得分:0)
添加Readonly
TextBoxID.Attributes.Add("readonly","true");
删除只读
TextBoxID.Attributes.Remove("readonly");
答案 3 :(得分:0)
经常需要一起在PropertyGrid中动态设置属性的可浏览或只读属性,它们也是类似的工作
触摸几下之后, Reza Aghaei 关于“ Hide some properties in PropertyGrid at run-time”的好答案也适用于操纵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());
}
}
及其用法:
propertyGrid1.SelectedObject = new CustomObjectWrapper(myobject);
答案 4 :(得分:0)
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);
}