WinForms Designer和TableLayoutPanel SmartTag自定义 [英] WinForms Designer and TableLayoutPanel SmartTag Customization

查看:51
本文介绍了WinForms Designer和TableLayoutPanel SmartTag自定义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试自定义TableLayoutPanel Windows窗体控件的现有智能标记内容,以供Windows窗体设计器中使用(我实现了一个利用System.ComponentModel.Design和System.Windows公开的WinForms设计器功能的设计器.Forms.Design名称空间).无论采用哪种方法作为解决方案,当将控件添加到Visual Studio工具箱中以及将控件放置在Visual Studio IDE中的设计模式下的WinForm曲面上时,它也必须起作用.

这就是我想要做的:在设计方式下,表单上的TableLayoutPanel控件实例显示装饰物,当单击该装饰物时,将显示由动作"组成的智能标记"面板,例如添加列",添加行"等.(这些动作中的某些还以动词形式出现在属性网格-我知道如何修改这些动词:我的问题只与智能标记操作列表有关.)

我要做的是用我自己的一些项修改TableLayoutPanel控件的设计时智能标记操作列表.

不幸的是,似乎要执行此操作,您必须将控件与自定义设计器相关联.但是,我不想使用自定义设计器或从ControlDesigner派生的设计器.我发现执行此操作时,我失去了TableLayoutPanel控件提供的所有设计器功能,例如看到新的行,列以及能够将控件拖放到其客户端表面上.我必须保留TableLayoutPanel的这种可视化设计时功能.

如果我使用Designer属性将TableLayoutPanelDesigner类指定为设计器,则我不走运,因为该类被标记为内部(

为此,您可以在设计时找到 TableLayoutPanel 的设计器并对其进行操作.好的一点是 OnHandleCreated 方法.您可以从控件的 Site 获取 IDesignerHost 的实例,然后获取设计器.

然后,您可以获得控件的当前操作列表,并创建一个包含所有这些操作项的新操作列表,并将一些新操作项添加到列表中.

MyTableLayoutPanel

 使用系统;使用System.ComponentModel.Design;使用System.Windows.Forms;使用System.Windows.Forms.Design;公共类MyTableLayoutPanel:TableLayoutPanel{私有IDesignerHost designerHost;受保护的重写void OnHandleCreated(EventArgs e){base.OnHandleCreated(e);如果(DesignMode&& Site!= null){designerHost = Site.GetService(typeof(IDesignerHost))作为IDesignerHost;如果(designerHost!= null){var designer =(ControlDesigner)designerHost.GetDesigner(this);如果(设计师!= null){var actions = designer.ActionLists [0];designer.ActionLists.Clear();designer.ActionLists.Add(新的MyTableLayoutPanelActionList(designer,actions));}}}}} 

MyTableLayoutPanelActionList

 使用System.ComponentModel;使用System.ComponentModel.Design;使用System.Drawing;使用System.Windows;使用System.Windows.Forms.Design;公共类MyTableLayoutPanelActionList:DesignerActionList{MyTableLayoutPanel控件;ControlDesigner设计器;DesignerActionList actionList;公共MyTableLayoutPanelActionList(ControlDesigner设计器,DesignerActionList actionList):base(designer.Component){this.designer =设计师;this.actionList = actionList;控件=(MyTableLayoutPanel)designer.Control;}公共颜色BackColor{得到{return control.BackColor;}放{TypeDescriptor.GetProperties(Component)["BackColor"].SetValue(Component,value);}}私人void DoSomething(){MessageBox.Show(已添加我的自定义动词!");}公共重写DesignerActionItemCollection GetSortedActionItems(){var items = new DesignerActionItemCollection();foreach(actionList.GetSortedActionItems()中的DesignerActionItem项)items.Add(item);var category =新动作";items.Add(new DesignerActionMethodItem(this,"DoSomething",做某事!",类别,正确));items.Add(new DesignerActionPropertyItem("BackColor","Back Color",类别));退换货品;}} 

I am trying to customize the existing Smart Tag content for a TableLayoutPanel Windows Forms control for use in the Windows Forms designer (I implemented a designer that leverages the WinForms designer features exposed by the System.ComponentModel.Design and System.Windows.Forms.Design namespaces). Whatever approach is offered as a solution, it's got to also work when my control is added to the Visual Studio toolbox and when my control is placed on a WinForm surface in design mode while in the Visual Studio IDE.

Here's what I'm trying to do: In design mode, a TableLayoutPanel control instance on a form displays an adornment that, when clicked, presents the Smart Tag panel composed of "actions", such as Add Column, Add Row, etc. (Some of these actions also appear as verbs under the property grid--I know how to modify those verbs: My question has to do with only the smart tag action list.)

What I want to do is amend the TableLayoutPanel control's design-time smart tag action list with some of my own items.

Unfortunately, it seems that to do this, you must associate the control with a custom designer. However, I don't want to use a custom designer or one that's derived from ControlDesigner. I found that when I do this, I lose all of the designer functionality the TableLayoutPanel control offers--such as seeing new rows, columns and being able to drag-and-drop controls onto its client surface. I must retain such visual design-time features of the TableLayoutPanel.

If I use the Designer attribute to specify the TableLayoutPanelDesigner class as the designer, then I'm out of luck because that class is marked as internal (https://referencesource.microsoft.com/#System.Design/System/Windows/Forms/Design/TableLayoutPanelDesigner.cs).

How can I leverage the existing designer for the WinForm TableLayoutPanel control yet also customize its smart tag's action list? Surely this must be accessible using reflection (but I couldn't figure out how).

解决方案

TableLayoutPanelDesiner is internal and has dependencies to other internal classes and you can not inherit from it. Also, it's not a good idea to create an new control designer for TableLayoutPanel from scratch because you will lose all of current designer functionalities.

A really good trick is finding the designer and manipulate designer at design-time. Look at the Do something! and the Back Color new items:

To do so, you can find the designer of your TableLayoutPanel at design-time and manipulate it. A good point is in OnHandleCreated method. You can get an instance of IDesignerHost from Site of the control and then get the designer.

Then you can get the current action list for the control and create a new action list containing all those action items and add some new action items to the list.

MyTableLayoutPanel

using System;
using System.ComponentModel.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
public class MyTableLayoutPanel : TableLayoutPanel
{
    private IDesignerHost designerHost;
    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        if (DesignMode && Site != null)
        {
            designerHost = Site.GetService(typeof(IDesignerHost)) as IDesignerHost;
            if (designerHost != null)
            {
                var designer = (ControlDesigner)designerHost.GetDesigner(this);
                if (designer != null)
                {
                    var actions = designer.ActionLists[0];
                    designer.ActionLists.Clear();
                    designer.ActionLists.Add(
                        new MyTableLayoutPanelActionList(designer, actions));
                }
            }
        }
    }
}

MyTableLayoutPanelActionList

using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Windows;
using System.Windows.Forms.Design;
public class MyTableLayoutPanelActionList : DesignerActionList
{
    MyTableLayoutPanel control;
    ControlDesigner designer;
    DesignerActionList actionList;
    public MyTableLayoutPanelActionList(ControlDesigner designer, 
        DesignerActionList actionList) : base(designer.Component)
    {
        this.designer = designer;
        this.actionList = actionList;
        control = (MyTableLayoutPanel)designer.Control;
    }
    public Color BackColor
    {
        get { return control.BackColor; }
        set
        {
            TypeDescriptor.GetProperties(Component)["BackColor"]
                .SetValue(Component, value);
        }
    }
    private void DoSomething()
    {
        MessageBox.Show("My Custom Verb added!");
    }
    public override DesignerActionItemCollection GetSortedActionItems()
    {
        var items = new DesignerActionItemCollection();
        foreach (DesignerActionItem item in actionList.GetSortedActionItems())
            items.Add(item);
        var category = "New Actions";
        items.Add(new DesignerActionMethodItem(this, "DoSomething", 
            "Do something!", category, true));
        items.Add(new DesignerActionPropertyItem("BackColor", "Back Color",
            category));
        return items;
    }
}

这篇关于WinForms Designer和TableLayoutPanel SmartTag自定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆