在VS设计器中公开类型列表的属性<class>限制/隐藏对成员的访问权限或将属性显示为可扩展菜单?

Jan*_*cci 6 c# custom-controls visual-studio-2010 user-defined-types custom-properties

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

[ToolboxItem(true)]    
public partial class CustomTabControl : System.Windows.Forms.TabControl
Run Code Online (Sandbox Code Playgroud)

为了存储每个单独的名称/字体对,我在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;
    }
}
Run Code Online (Sandbox Code Playgroud)

(注意在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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

private List<TabFont> _CustomTabFonts = new List<TabFont>();
Run Code Online (Sandbox Code Playgroud)

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

this.ControlAdded += new ControlEventHandler(CustomTabControl_ControlAdded);
Run Code Online (Sandbox Code Playgroud)

以下是我在事件处理程序中填充列表的方法:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,为了完成这一切,我定义了以下代码,允许Visual Studio设计器访问/修改自定义选项卡字体列表:

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

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

这是我的自定义选项卡字体属性的属性框显示的内容:

自定义选项卡字体属性

请注意,它将类型显示为集合,并提供单击以进行编辑的按钮.当我点击这里的按钮时,我看到的是:

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

关于属性编辑器,我有几个问题.

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

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

  • 属性编辑器的左侧有一个名为"Members"的标题.我可以改变它来说出我想要的东西吗?类似"标签页"等的东西

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

非常感谢你.

一月

____UPDATE____

如果有更好/不同的方式来做我想做的事情,我愿意接受所有的建议.我是新手,到目前为止我所做的工作基于不同网站的各种结果.

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

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

小智 0

我无法回答更新问题,但我会尝试另外两个问题:更改文本“Members”:我能看到执行此操作的唯一方法是创建一个自定义 CollectionEditor,它打开一个自定义 CollectionEditor.CollectionForm 。我还没有尝试过这个。阻止“Name”属性出现在编辑器中:是的,这可以在 TypeConverter.GetProperties 方法中通过过滤结果来完成。我没有发现 TypeDescriptor.GetProperties 方法的“filter”参数有任何用处,但这可能是因为我没有正确使用它。问题是,一旦创建,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;
        }
Run Code Online (Sandbox Code Playgroud)