C# Winform CollectionPropertiesEditor - 如何根据运行时条件隐藏内置 PropertyGrid 中的某些属性

标签 c# .net winforms windows-forms-designer propertygrid

有没有办法隐藏“CollectionPropertiesEditor's PropertyGrid”中的显示属性 最近我发现有一种方法可以在运行时更改PropertyGrid的Browsable属性。

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

问题:由于新的客户要求,我必须向 GridColumn 控件添加一些属性。

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

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

我希望早点工作:

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

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

为什么不起作用?

因为Browsable Attribute只能接受Constant。并且 matchSomeRunTimeCondition 不是常量。用户可以在应用程序仍在运行时随时更改它。

在代码中,如果我可以使用一个函数使它们在运行时不可见,如果有人可以帮助我编写一个这样的函数或条件语句,我将非常感激:

If (property’s category == “Extra”) {

//Do not show this property in the propertygrid.

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

}

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

通过在加载所选控件时进行设置,属性网格中解决了此问题,如帖子所述:Make all properties with specific Category name invisible in PropertyGrid in c# Winforms at Runtime based on some condition

但是,在我用来保存网格列的 CollectionPropertiesEditor 中,没有这种奢侈(至少我不知道如何做到这一点)。

我以 GridColumns 列表的形式将网格的所有网格列存储为属性。

这就是我当前在网格属性中存储 GridColumn 的方式:

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

enter image description here

enter image description here 这里我不知道如何传递我的条件以使上述列在运行时消失。

最佳答案

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

我的PropertyDescriptor

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

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

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

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

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

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

包含一个用[Category("Extra")]装饰的属性。因此 Property2 在属性网格中将不可见。 (在 Visual Studio 或集合编辑器甚至运行时属性网格中)

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

MyComplexComponent

包含MySampleClass的集合。因此您可以在集合编辑器中看到 MySampleClass 的行为。

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

屏幕截图

enter image description here

关于C# Winform CollectionPropertiesEditor - 如何根据运行时条件隐藏内置 PropertyGrid 中的某些属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42826224/

相关文章:

c# - 登录控制和自定义成员(member)提供者

c# - 为什么我的查询字符串参数被 url 解码两次?

c# - Visual Studio 在运行程序后向 DataGridView 添加列

c# - MailMessage 问题/困惑

c# - Selenium 如何使用 chromedriver 和 C# 清除缓存

c# - 如何在Xamarin Forms中查看 'customized'?

c# - 我可以调试带有源断点的 nuget 包而不是单步执行吗?

.net - .NET 中非 CLS 兼容代码的后果是什么?

c# - 如果是 .NET Framework 的 .NET 库,如何在 OSX 中使用 GemBox.Spreadsheet

c# - 为什么文本在 RichTextBox 中消失了?