Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 动态设置PropertyGrid中属性的只读属性_C#_.net_Winforms_Readonly_Propertygrid - Fatal编程技术网

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,然后将其重置。我不确定,您也可以使用PropertyGrid
RefreshTabs
方法来实现这一点

编辑:


不幸的是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文章的死链接。