【问题标题】:C# Winform CollectionPropertiesEditor - How to hide some properties in the built-in PropertyGrid based on runtime conditionC# Winform CollectionPropertiesEditor - 如何根据运行时条件隐藏内置 PropertyGrid 中的某些属性
【发布时间】:2017-03-16 05:48:59
【问题描述】:

有没有办法在“CollectionPropertiesEditor 的 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 不是一个常数。用户可以在应用程序仍在运行时随时更改它。

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

如果(属性类别 == “额外”){

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

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

}

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

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

但是在我用来保存我的网格列的 CollectionPropertiesEditor 中没有这种奢侈(至少我不知道该怎么做)。

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

这就是我当前在 Grid 的属性中存储 GridColumns 的方式:

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

这里我不知道如何通过我的条件使上述列在运行时消失。

【问题讨论】:

  • 您应该通过派生自CustomTypeDescriptor 或实现ICustomTypeDescriptor 来编写自己的类型描述符。例如看看这篇文章:Combining multiple Attributes to a single Attribute
  • 嗨@RezaAghaei,很高兴见到你这么久。让我检查一下您的解决方案并返回(可能需要一些时间)。
  • 嗨,也很高兴见到你:)
  • @RezaAghaei,我不明白如何使用您的解决方案来解决这个问题。
  • @RezaAghaei,您知道创建自定义 CollectionPropertiesEditor 是否需要花费太多精力吗?

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


【解决方案1】:

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

MyPropertyDescriptor

为属性提供自定义描述。在这里,我覆盖 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

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

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

我的复杂组件

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

截图

【讨论】:

  • 哇@RezaAghaei,多么快速的解决方案。我会在尝试你的答案后回来。我需要一些时间来了解发生了什么。
  • 没问题。这就是类型描述符的工作方式。它们是在属性网格中使用的元数据引擎。
  • 我将您的代码复制到单独的 .cs 文件中,这些文件的名称与上面为每个代码示例提供的标题相同。你能告诉我使屏幕截图出现的代码吗?
  • 构建您的项目并在表单上放置 MyComplexComponent。然后检查它的MySampleClasses 属性,它会打开一个集合编辑器。
  • 我之前没有注意到。它出现在工具箱中,并显示在表单下方。
猜你喜欢
  • 2019-01-07
  • 2013-09-26
  • 2023-01-10
  • 1970-01-01
  • 2022-09-27
  • 1970-01-01
  • 1970-01-01
  • 2021-08-01
  • 2012-12-20
相关资源
最近更新 更多