Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
521 views
in Technique[技术] by (71.8m points)

c# - WinForms Designer and TableLayoutPanel SmartTag Customization

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).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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:

enter image description here

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...