C# Winform CollectionPropertiesEditor - 如何根据运行时条件隐藏内置PropertyGrid中的一些属性 [英] C# Winform CollectionPropertiesEditor - How to hide some properties in the built-in PropertyGrid based on runtime condition

查看:41
本文介绍了C# Winform CollectionPropertiesEditor - 如何根据运行时条件隐藏内置PropertyGrid中的一些属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法在CollectionPropertiesEditor's PropertyGrid"中隐藏显示属性最近发现有一种方法可以在运行时改变PropertyGrid的Browsable属性.

我想知道是否可以对CollectionPropertiesEditor 的 PropertyGrid"执行此操作,但我未能在 Google 搜索上找到相关结果.现在我希望 StackOverflow 帮助我解决这个问题.

问题:由于新的客户需求,我不得不向 GridColumn 控件添加一些属性.

 [类别(额外")][可浏览(真)]公众号?位置{得到;放;}[类别(额外")][可浏览(真)]公共字符串存储列 { 获取;放;}

我希望早些工作:

 [类别(额外")][可浏览(matchSomeRunTimeCondition)]公众号?位置{得到;放;}[类别(额外")][可浏览(matchSomeRunTimeCondition)]公共字符串存储列 { 获取;放;}

为什么它不起作用?

因为可浏览属性只能接受常量.而 matchSomeRunTimeCondition 不是一个常数.用户可以在应用程序仍在运行时随时更改它.

在代码中,如果有一个函数可以让我在运行时使这些不可见,如果有人能帮我写一个这样的函数或条件语句,我会非常高兴:

<块引用>

如果(属性的类别==额外"){

//在propertygrid中不显示该属性.

//或者换句话说,在运行时将Browasable Attribute设为False.

}

在编译时我将 Browsable 属性设置为 true 因为它需要在某些条件下可见.但是我需要一种机制来根据用户在运行时的选择来隐藏它.

通过在加载所选控件时设置它,在属性网格中克服了这个问题,如帖子所述:

这里我不知道如何传递我的条件让上述列在运行时消失.

解决方案

您应该通过从 CustomTypeDescriptor 派生或实现 ICustomTypeDescriptor 来编写自己的类型描述符.下面是一个例子:

MyPropertyDescriptor

为属性提供自定义描述.在这里,我覆盖了 Attributes 属性以提供属性的新属性列表.例如,我检查该属性是否具有 [Category("Extra")],我还在其属性集合中添加了一个 [Browsable(false)].

使用系统;使用 System.ComponentModel;使用 System.Linq;公共类 MyPropertyDescriptor :PropertyDescriptor{属性描述符 o;公共 MyPropertyDescriptor(PropertyDescriptor originalProperty):基础(原始属性){ o = 原始属性;}public override bool CanResetValue(对象组件){ 返回 o.CanResetValue(组件);}公共覆盖对象 GetValue(对象组件){ 返回 o.GetValue(组件);}公共覆盖无效重置值(对象组件){ o.ResetValue(组件);}公共覆盖无效 SetValue(对象组件,对象值){ o.SetValue(component, value);}public override bool ShouldSerializeValue(对象组件){ 返回 o.ShouldSerializeValue(组件);}公共覆盖 AttributeCollection 属性{得到{var attributes = base.Attributes.Cast().ToList();var category = attributes.OfType().FirstOrDefault();if (category != null && category.Category == "Extra")attributes.Add(new BrowsableAttribute(false));返回新的 AttributeCollection(attributes.ToArray());}}公共覆盖类型 ComponentType { get { return o.ComponentType;} }公共覆盖 bool IsReadOnly { get { return o.IsReadOnly;} }公共覆盖类型 PropertyType { get { return o.PropertyType;} }}

MyTypeDescriptor

用于提供类型的自定义属性描述符列表.

使用系统;使用 System.ComponentModel;使用 System.Linq;公共类 MyTypeDescriptor :CustomTypeDescriptor{ICustomTypeDescriptor 原始;公共 MyTypeDescriptor(ICustomTypeDescriptor originalDescriptor): base(originalDescriptor) { original = originalDescriptor;}公共覆盖 PropertyDescriptorCollection GetProperties(){ return this.GetProperties(new Attribute[] { });}公共覆盖 PropertyDescriptorCollection GetProperties(Attribute[] 属性){var properties = base.GetProperties(attributes).Cast().Select(p => new MyPropertyDescriptor(p)).ToArray();返回新的 PropertyDescriptorCollection(properties);}}

MyTypeDescriptionProvider

用于将 MyTypeDescriptor 连接到使用 TypeDescriptionProvider 属性的类.

使用系统;使用 System.ComponentModel;公共类 MyTypeDescriptionProvider :TypeDescriptionProvider{公共 MyTypeDescriptionProvider(): 基础(TypeDescriptor.GetProvider(typeof(object))) { }公共覆盖 ICustomTypeDescriptor GetTypeDescriptor(类型类型,对象 o){ICustomTypeDescriptor baseDescriptor = base.GetTypeDescriptor(type, o);返回新的 MyTypeDescriptor(baseDescriptor);}}

MySampleClass

包含用 [Category("Extra")] 修饰的属性.所以 Property2 在属性网格中将不可见.(在 Visual Studio 或集合编辑器甚至运行时属性网格中)

[TypeDescriptionProvider(typeof(MyTypeDescriptionProvider))]公共类 MySampleClass{公共 int Property1 { 得到;放;}[类别(额外")]公共字符串 Property2 { 获取;放;}}

MyComplexComponent

包含 MySampleClass 的集合.所以你可以在集合编辑器中看到 MySampleClass 的行为.

使用 System.Collections.ObjectModel;使用 System.ComponentModel;公共类 MyComplexComponent:Component{公共 MyComplexComponent(){MySampleClasses = new Collection();}[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]公共集合MySampleClasses { 获取;放;}}

截图

Is there a way to hide show properties in "CollectionPropertiesEditor’s PropertyGrid" Recently I found out that there is a way to change the PropertyGrid’s Browsable attribute at run time.

I want to know if this can be done to a "CollectionPropertiesEditor’s PropertyGrid", I have been un-successful at finding relevant results on Google Search. Now I have my hopes on StackOverflow to help me solve this problem.

Problem: I had to add some properties to GridColumn control due to new customer requirements.

    [Category("Extra")]
    [Browsable(true)]
    public int? Position { get; set; }

    [Category("Extra")]
    [Browsable(true)]
    public string storedColumn { get; set; }

What I was hoping to work earlier:

    [Category("Extra")]
    [Browsable(matchSomeRunTimeCondition)]
    public int? Position { get; set; }

    [Category("Extra")]
    [Browsable(matchSomeRunTimeCondition)]
    public string storedColumn { get; set; }

Why it does not work?

Because Browsable Attribute can only accept Constant. And matchSomeRunTimeCondition is not a constant. A user can change it when-ever he wants while the application is still running.

In code if there is a function that I can use to make these invisible at run-time I will be really greatful if someone can help me write one such function or conditional statement like so:

If (property’s category == "Extra") {

//Do not show this property in the propertygrid.

//Or in other words, make Browasable Attribute False at run time.

}

At compile time I am setting the Browsable property to true because it needs to be visible in some conditions. But I need a mechanism to hide this based on user's choice at runtime.

This problem was overcome in the propertygrid by means of setting it while loading the selected control as explained the post: Make all properties with specific Category name invisible in PropertyGrid in c# Winforms at Runtime based on some condition

However in the CollectionPropertiesEditor that I use to hold my grid columns does not have this luxury (at least I could not find out how to do it).

I store all the grid columns of my grid in the form of list of GridColumns as a property.

This is how I am currently storing the GridColumns in the Grid’s properties:

    [Browsable(true)]
    [Editor(typeof(CollectionPropertiesEditor), typeof(UITypeEditor))]
    public List<TGridColumn> Columns { get; set; }

Here I don’t know how to pass my condition to make the aforementioned columns disappear at runtime.

解决方案

You should write your own type descriptor by deriving from CustomTypeDescriptor or implementing ICustomTypeDescriptor. Here is an example:

MyPropertyDescriptor

Provide a custom description for a property. Here I override Attributes property to provide a new list of attributes for property. For example I check if the property has [Category("Extra")], I also added a [Browsable(false)] to its attribute collection.

using System;
using System.ComponentModel;
using System.Linq;
public class MyPropertyDescriptor : PropertyDescriptor
{
    PropertyDescriptor o;
    public MyPropertyDescriptor(PropertyDescriptor originalProperty)
        : base(originalProperty) { o = originalProperty; }
    public override bool CanResetValue(object component)
    { return o.CanResetValue(component); }
    public override object GetValue(object component) { return o.GetValue(component); }
    public override void ResetValue(object component) { o.ResetValue(component); }
    public override void SetValue(object component, object value) 
    { o.SetValue(component, value); }
    public override bool ShouldSerializeValue(object component) 
    { return o.ShouldSerializeValue(component); }
    public override AttributeCollection Attributes
    {
        get
        {
            var attributes = base.Attributes.Cast<Attribute>().ToList();
            var category = attributes.OfType<CategoryAttribute>().FirstOrDefault();
            if (category != null && category.Category == "Extra")
                attributes.Add(new BrowsableAttribute(false));
            return new AttributeCollection(attributes.ToArray());
        }
    }
    public override Type ComponentType { get { return o.ComponentType; } }
    public override bool IsReadOnly { get { return o.IsReadOnly; } }
    public override Type PropertyType { get { return o.PropertyType; } }
}

MyTypeDescriptor

Used to provide a list of custom property descriptors for a type.

using System;
using System.ComponentModel;
using System.Linq;
public class MyTypeDescriptor : CustomTypeDescriptor
{
    ICustomTypeDescriptor original;
    public MyTypeDescriptor(ICustomTypeDescriptor originalDescriptor)
        : base(originalDescriptor) { original = originalDescriptor; }
    public override PropertyDescriptorCollection GetProperties()
    { return this.GetProperties(new Attribute[] { }); }
    public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
    {
        var properties = base.GetProperties(attributes).Cast<PropertyDescriptor>()
                             .Select(p => new MyPropertyDescriptor(p))
                             .ToArray();
        return new PropertyDescriptorCollection(properties);
    }
}

MyTypeDescriptionProvider

Used to connect MyTypeDescriptor to a class using TypeDescriptionProvider attribute.

using System;
using System.ComponentModel;
public class MyTypeDescriptionProvider : TypeDescriptionProvider
{
    public MyTypeDescriptionProvider()
        : base(TypeDescriptor.GetProvider(typeof(object))) { }

    public override ICustomTypeDescriptor GetTypeDescriptor(Type type, object o)
    {
        ICustomTypeDescriptor baseDescriptor = base.GetTypeDescriptor(type, o);
        return new MyTypeDescriptor(baseDescriptor);
    }
}

MySampleClass

Contains a property decorated with [Category("Extra")]. So Property2 will not be visible in property grid. (In visual studio or collection editor or even run-time property grid)

[TypeDescriptionProvider(typeof(MyTypeDescriptionProvider))]
public class MySampleClass
{
    public int Property1 { get; set; }
    [Category("Extra")]
    public string Property2 { get; set; }
}

MyComplexComponent

Contains a collection of MySampleClass. So you can see behavior of MySampleClass in collection editor.

using System.Collections.ObjectModel;
using System.ComponentModel;
public class MyComplexComponent:Component
{
    public MyComplexComponent()
    {
        MySampleClasses = new Collection<MySampleClass>();
    }
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public Collection<MySampleClass> MySampleClasses { get; set; }
}

Screenshot

这篇关于C# Winform CollectionPropertiesEditor - 如何根据运行时条件隐藏内置PropertyGrid中的一些属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆