6

我为我的 Windows 应用程序创建了一个自定义选项卡控件。自定义选项卡控件扩展了 System.Windows.Forms.TabControl。我创建自定义选项卡控件的原因是我可以在 Visual Studio 属性窗口中公开一个属性,该属性允许我为自定义选项卡控件中的每个选项卡页定义单独的字体。下面是类定义的快速浏览:

[ToolboxItem(true)]    
public partial class CustomTabControl : System.Windows.Forms.TabControl

为了存储每个单独的名称/字体对,我在 CustomTabControl 中创建了一个嵌套类:

[TypeConverter(typeof(TabFontConverter))]
public class TabFont
{
    public string Name { get; set; }
    public Font Font { get; set; }        
    public TabFont()
    {
    }        
    public TabFont(string name, Font font)
    {
        this.Name = name;
        this.Font = font;
    }
}

(注意在 TabFont 类上方使用TypeConverter属性。我添加了这个是因为我在网上读到的某个地方,如果我要在 Visual Studio 设计器中公开这种类型,这是必需的。)

这是转换器类(也嵌套在 CustomTabControl 中):

public class TabFontConverter : TypeConverter
{
    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] filter)
    {
        return TypeDescriptor.GetProperties(value, filter);
    }

    public override bool GetPropertiesSupported(ITypeDescriptorContext context)
    {
        return true;
    }
}

我定义了一个类变量来将自定义选项卡字体存储为列表:

private List<TabFont> _CustomTabFonts = new List<TabFont>();

为了填充这个列表,我为ControlAdded添加了一个事件处理程序:

this.ControlAdded += new ControlEventHandler(CustomTabControl_ControlAdded);

这是我在事件处理程序中填充列表的方式:

private void CustomTabControl_ControlAdded(object sender, ControlEventArgs e)
{
    if (e.Control.GetType() == typeof(TabPage))
    {
        TabPage newTabPage = (TabPage)e.Control;
        Font newTabPageFont = newTabPage.Font;
        _CustomTabFonts.Add(new TabFont(newTabPage.Text, newTabPageFont));
        e.Control.Font = newTabPageFont;
    }
}

最后,为了将这一切联系起来,我定义了以下代码,允许 Visual Studio 设计人员访问/修改自定义选项卡字体列表:

[DefaultValue(typeof(List<TabFont>))]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
public List<TabFont> CustomTabFonts
{
    get { return _CustomTabFonts; }
    set { _CustomTabFonts = value; }
}

重建后,我切换回 Visual Studio 设计视图,通过从工具箱中拖动一个 CustomTabControl 将一个 CustomTabControl 添加到我的主窗体中。然后我添加了两个名为“Tab 1”和“Tab 2”的标签页。

这是我的自定义标签字体属性的属性框显示的内容:

自定义标签字体属性

请注意,它将类型显示为 Collection 并提供一个按钮 [...] 以单击以进行编辑。当我单击此处的按钮时,我看到的是:

自定义选项卡字体属性编辑器

我有几个关于属性编辑器的问题。

  • 属性编辑器的右侧显示所选选项卡的字体和名称。我只希望能够更改字体,而不是名称。如何隐藏名称字段或至少使其只读?(我希望名称字段根本不显示在那里,因为我不想能够更改它,而且它也是多余的,因为名称已经显示在属性编辑器的左侧。)

  • 属性编辑器的左侧显示了我想要的选项卡列表。但是,我不希望允许移动、添加或删除任何这些成员。如何隐藏或禁用移动(向上/向下箭头)和添加/删除按钮?

  • 属性编辑器的左侧有一个名为“成员”的标题。我可以改变它来表达我想要的任何东西吗?诸如“标签页”之类的东西。

  • 属性编辑器的右侧有一个名为“Misc”的标题。我也可以改变吗?

非常感谢。

____更新____

如果有更好/不同的方式来做我想做的事情,我愿意接受所有建议。我对此很陌生,到目前为止我所做的都是基于来自不同网站的各种结果。

我真的希望我的属性出现在设计器中,类似于显示边距的方式。我想要一个可扩展的列表,而不是带有标签页/属性列表的弹出窗口,每个列表项都是标签名称后跟字体,然后您可以单击它来仅编辑字体。类似于以下内容:

自定义选项卡字体属性首选

4

1 回答 1

0

我无法回答更新问题,但我会尝试其他两个问题:更改文本“成员”:我能看到的唯一方法是创建一个自定义 CollectionEditor,它会打开一个自定义 CollectionEditor.CollectionForm . 我还没有尝试过这个。阻止“名称”属性出现在编辑器中:是的,这可以通过过滤结果在 TypeConverter.GetProperties 方法中完成。我没有发现 TypeDescriptor.GetProperties 方法的“过滤器”参数有任何用处,但这可能是因为我没有正确使用它。问题是,一旦创建,PropertyDescriptorCollection 是只读的,所以我复制了结果的内容,但错过了我不想要的项目。这应该有效:

    public class TabFontConverter : TypeConverter
    {
        public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] filter)
        {
            PropertyDescriptorCollection rawResult = TypeDescriptor.GetProperties(value, filter);
            PropertyDescriptor[] arrRawResult = new PropertyDescriptor[rawResult.Count - 1];

            int i = 0;
            int j = 0;
            while (i < rawResult.Count)
            {
                if (rawResult[i].Name != "Name")
                {
                    arrRawResult[j] = rawResult[i];
                    j++;
                }
                i++;
            }
            PropertyDescriptorCollection filteredResult = new PropertyDescriptorCollection(arrRawResult);

            return filteredResult;
        }
于 2017-05-21T15:52:53.003 回答