首页 > 解决方案 > PropertyGrid:仅为特定属性删除自定义数据类型的属性

问题描述

首先:问题的措辞可能不准确,对此深表歉意。实际问题在所有代码片段下方。
第二:代码是C#,但我通常用VB.NET编写代码。

我有一个类LabelData,其中包含用户绘制标签的视觉外观数据。简短的例子:

public class LabelData
{
    public Color BackColor1 { get; set; }
    public Color BackColor2 { get; set; }
    public Color TextColor { get; set; }
    public int TextAngle { get; set; }
    public string Text { get; set; }
}

UserControl使用LabelData. 它看起来像这样(简化):

public class UserControl1
{
    public LabelData Title { get; set; }

    protected override void OnPaint(PaintEventArgs e)
    {
        // draw title here

        LabelData currentLabel;

        for (int i = 0; i <= 9; i++)
        {
            currentLabel = new LabelData();
            currentLabel.BackColor1 = Color.Green;
            currentLabel.BackColor2 = Color.YellowGreen;
            currentLabel.TextAngle = 0;
            currentLabel.Text = "Element" + i.ToString();

            // draw text here
        }
    }
}

小标签的所有数据都在OnPaint. 我不想要这个。我想到了一个用于较小标签的模板,例如DataGridViewRowTemplate. 这也允许我实现ICloneablefor LabelData

这将更改为:

public class UserControl1
{
    public LabelData Title { get; set; }
    public LabelData LabelTemplate { get; set; }

    protected override void OnPaint(PaintEventArgs e)
    {
        LabelData currentLabel;

        for (int i = 0; i <= 9; i++)
        {
            currentLabel = LabelTemplate.Clone();
            currentLabel.Text = "Element" + i.ToString();
        }
    }
}

现在的问题是:我如何删除Text-Property 中的LabelTemplate属性(但不是Title属性),PropertyGrid因为这个属性OnPaint无论如何都会改变?

PS:我尝试创建一个自定义设计器并覆盖PreFilterProperties以删除该Text属性,但我无法向该属性添加DesignerAttribute一个LabelTemplate

标签: c#.netvb.netwinformsuitypeeditor

解决方案


由于您可能需要ExpandableObjectConverter来呈现从 Class 对象分配的属性,因此当您希望在特定情况下以不同方式呈现此对象时LabelData,您可以基于基类对象创建自定义 TypeConverter并从中删除属性。ExpandableObjectConverter

在这里,作为示例,虽然TitleTemplate属性在 PropertyGrid 中都显示为可扩展对象(因此您可以使用其特定的类型编辑器编辑每个属性值),但该Template属性具有稍微不同的类型转换器,其中 GetProperties()方法被覆盖以删除Text来自底层 Class 对象的属性,因此它不会显示在 PropertyGrid 中:

自定义 ExpandableObjectConverter

Template 可扩展对象属性未将 Text 属性显示为其同伴 Title 属性

C#版本

public class UserControl1
{
    public UserControl1() {
        Template = new LabelData() { ... };
        Title = new LabelData() { ... };
    }

    [TypeConverter(typeof(ExpandableObjectConverter))]
    public LabelData Title { get; set; }

    [TypeConverter(typeof(CustomExpandableConverter))]
    public LabelData Template { get; set; }

    // [...]
}

public class CustomExpandableConverter : ExpandableObjectConverter
{
    public CustomExpandableConverter() { }

    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
    {
        var props = base.GetProperties(context, value, attributes)
                        .OfType<PropertyDescriptor>().Where(pd => pd.Name != "Text").ToArray();
        return new PropertyDescriptorCollection(props);
    }
}

VB.Net 版本

Public Class UserControl1
    Public Sub New()
        Template = New LabelData()
        Title = New LabelData()
    End Sub

    <TypeConverter(GetType(ExpandableObjectConverter))>
    Public Property Title As LabelData

    <TypeConverter(GetType(CustomExpandableConverter))>
    Public Property Template As LabelData

    '[...]
End Class

Public Class CustomExpandableConverter
    Inherits ExpandableObjectConverter

    Public Sub New()
    End Sub

    Public Overrides Function GetProperties(context As ITypeDescriptorContext, value As Object, attributes() As Attribute) As PropertyDescriptorCollection
        Dim props = MyBase.GetProperties(context, value, attributes).
                           OfType(Of PropertyDescriptor)().
                           Where(Function(pd) Not pd.Name.Equals("Text")).ToArray()
        Return New PropertyDescriptorCollection(props)
    End Function
End Class

推荐阅读