【问题标题】:PropertyGrid readonly property on object-level对象级的 PropertyGrid 只读属性
【发布时间】:2012-05-15 22:51:42
【问题描述】:

我想在我的PropertyGrid 中显示一个类的多个实例。该类如下所示:

public class Parameter
{
    [Description("the name")]
    public string Name { get; set; }

    [Description("the value"), ReadOnly(true)]
    public string Value { get; set; }

    [Description("the description")]
    public string Description { get; set; }
}

我在TreeView 中有许多该类的实例。当我在TreeView 中选择其中一个时,属性会按预期显示在PropertyGrid 中。到目前为止一切顺利,但我想通过以下方式自定义此行为:

对于每个实例,我希望能够防止用户修改特定属性。通过在我的类中设置ReadOnly(true)(如您在上面的示例中所见),所有Value 属性都将在类级别上被禁用。

经过一些研究,我发现了以下解决方案,它让我有机会在运行时启用/禁用特定属性:

PropertyDescriptor descriptor = TypeDescriptor.GetProperties(this)["Value"];

ReadOnlyAttribute attr = 
        (ReadOnlyAttribute)descriptor.Attributes[typeof(ReadOnlyAttribute)];

FieldInfo isReadOnly = attr.GetType().GetField(
        "isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);

isReadOnly.SetValue(attr, false);

这种方法效果很好,但不幸的是也只​​在类级别上。这意味着如果我将ValueisReadOnly 设置为false,我的Parameter 对象的所有 都具有Value 可写属性。但我只希望在那个特定的对象上使用它(因此 object-level)。我真的不想为读/写和只读属性创建单独的类。

由于我的想法不多了,非常感谢您的帮助:)

提前致谢!

编辑:我需要将只读属性设为灰色,以便用户可以看到不允许或无法编辑它们。

【问题讨论】:

    标签: c# .net propertygrid propertydescriptor readonly-attribute


    【解决方案1】:

    您可以使用自定义类型描述符来包装对象,但我认为这太过分了,因为您必须创建一个新的类型描述符派生类。

    因此,最简单的解决方案是设置一个标志,例如:

    public class Parameter 
    { 
        private string thevalue;
    
        [Browsable(false)]
        public bool CanEditValue { get; set; }
    
        [Description("the name")] 
        public string Name { get; set; } 
    
        [Description("the description")] 
        public string Description { get; set; }
    
        [Description("the value"), ReadOnly(true)] 
        public string Value { 
            get { return this.thevalue; }
            set { if (this.CanEditValue) this.thevalue = value; } 
        }
    }
    

    【讨论】:

    • 你好 Jaime,你的双倍属性建议是可以接受的,因为它真的很简单。我试过这个,不幸的是,在 setter 中检查并没有禁用像 ReadOnly(true) 这样的属性编辑......所以它没有变灰。用户会认为它是可变的,但他们的输入将被丢弃。还有其他不那么复杂的想法吗? :)
    • 恐怕你唯一的选择是派生一个属性描述符并实现条件 IsReadOnly 属性获取器。
    【解决方案2】:

    编辑:链接的文章已被删除(我希望只是暂时的)。您可以在How to add property-level Attribute to the TypeDescriptor at runtime? 的答案中找到一个可行的替代方案。基本上,您必须通过TypeDescriptor 为该属性添加(在运行时)ReadOnlyAttribute


    看看这个古老但不错的article on CodeProject,它包含很多对PropertyGrid 有用的工具

    基本上,您提供一个类或一个委托,用于获取您的属性的属性。因为它将通过传递您想要获取属性的对象的实例来调用,所以您将能够以每个对象为基础返回(或不返回)ReadOnlyAttribute。很快:将PropertyAttributesProviderAttribute 应用于您的属性,编写您自己的提供程序并根据对象本身(而不是类)替换PropertyAttributes 集合中的属性

    【讨论】:

    • 我已经阅读了整个文档,但仍然不明白您的想法。您能否提供一个小代码示例以使其更清晰?谢谢你的时间:)
    • 请参阅该文章中的动态用法段落。很快:将 PropertyAttributesProviderAttribute 应用于您的属性,编写您自己的提供程序并根据对象本身(而不是类)替换 PropertyAttributes 集合中的属性。
    • 正如我在源代码中看到的,这需要使用作者自定义的 PropertyGrid 实现来使其工作吗?在我的情况下,我必须使用 DLL 中的现有 PropertyGrid(我无法修改)。
    • @Inferno 不,一切都是通过自定义属性和类型描述符完成的。
    • 终于想通了。我忘记将 TypeConverterAttribute 放在班级的顶部。仍然有很多代码可以解决这样一个小问题......但主要的是它现在正在工作。谢谢!
    猜你喜欢
    • 2015-09-03
    • 1970-01-01
    • 2010-12-05
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多