简体   繁体   English

PropertyGrid对象级别的readonly属性

[英]PropertyGrid readonly property on object-level

I want to display multiple instances of one class in my PropertyGrid . 我想在PropertyGrid显示一个类的多个实例。 The class looks like this: 这个类看起来像这样:

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; }
}

I have many instances of that class in a TreeView . 我在TreeView有很多类的实例。 When I select one of them in my TreeView , the properties show up in the PropertyGrid as expected. 当我在TreeView选择其中一个时, PropertyGrid按预期显示在PropertyGrid中。 So far so good, but I want to customise this behaviour in the following way: 到目前为止一切顺利,但我想以下列方式自定义此行为:

For each single instance I want to be able to prevent the user from modifying a specific property. 对于每个单个实例,我希望能够阻止用户修改特定属性。 By setting ReadOnly(true) within my class (as you can see in the example above), all Value properties will be disabled on a class-level . 通过在我的类中设置ReadOnly(true) (如上例中所示),将在类级别禁用所有Value属性。

After some research I found the following solution which gives me the opportunity to enable/disable a specific property at runtime: 经过一些研究后,我发现以下解决方案让我有机会在运行时启用/禁用特定属性:

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);

This approach works just fine but unfortunately also on class-level only. 这种方法运行得很好但不幸的是也只​​在类级别上。 This means if I set the Value 's isReadOnly to false , all of my Parameter -objects have the Value property writeable. 这意味着如果我将ValueisReadOnlyfalse那么我的所有 Parameter -objects都会将Value属性设置为可写。 But I want this ONLY on that one particular object (thus object-level ). 但我只希望这个特定的对象(因此对象级 )。 I really don't want to create separate classes for read/write and readonly properties. 我真的不想为读/写和只读属性创建单独的类。

As I am running out of ideas, your help is much appreciated :) 由于我的想法用完了,所以非常感谢你的帮助:)

Thanks in advance! 提前致谢!

EDIT: I need the readonly properties to be grayed-out, so the user can see that it's not allowed or possible to edit them. 编辑:我需要将readonly属性显示为灰色,以便用户可以看到不允许或不可能编辑它们。

EDIT : Linked article has been removed (I hope just temporary). 编辑 :链接的文章已被删除(我希望只是暂时的)。 You can fine a viable alternative in answers to How to add property-level Attribute to the TypeDescriptor at runtime? 您可以在如何在运行时将属性级属性添加到TypeDescriptor的答案中找到可行的替代方案吗? . Basically you have to add (at run-time) ReadOnlyAttribute through a TypeDescriptor for that property. 基本上,您必须通过TypeDescriptor为该属性添加(在运行时) ReadOnlyAttribute


Take a look at this old but nice article on CodeProject , it contains a lot of useful tools for the PropertyGrid . 看一下关于CodeProject的这篇古老但不错的文章 ,它包含了很多有用的PropertyGrid 工具

Basically you provide a class or a delegate that will be used to get the attributes of your properties. 基本上,您提供了一个类或委托,用于获取属性的属性。 Because it will be invoked passing the instance of the object you want to get attributes for then you'll be able to return (or not) the ReadOnlyAttribute with a per object basis. 因为它将被调用传递您想要获取属性的对象的实例,所以您将能够以每个对象为基础返回(或不返回) ReadOnlyAttribute Shortly: apply a PropertyAttributesProviderAttribute to your property, write your own provider and replace attributes from the PropertyAttributes collection based on the object itself (and not on the class) 简而言之:将PropertyAttributesProviderAttribute应用于您的属性,编写您自己的提供程序并根据对象本身(而不是类)替换PropertyAttributes集合中的PropertyAttributes

You can wrap the object with a custom type descriptor, but I think that would be overkill, because you have to create a new typedescriptor-derived class. 您可以使用自定义类型描述符包装对象,但我认为这样会有点过分,因为您必须创建一个新的typedescriptor派生类。

So, a simplest solution would be to have a flag, something like: 所以,最简单的解决方案是拥有一个标志,例如:

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; } 
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM