WinForms Designer и настройка SmartTag TableLayoutPanel - PullRequest
0 голосов
/ 07 сентября 2018

Я пытаюсь настроить существующее содержимое смарт-тега для элемента управления Windows Forms TableLayoutPanel для использования в конструкторе Windows Forms (я реализовал дизайнер, использующий функции дизайнера WinForms, предоставляемые System.ComponentModel.Design и System.Windows. Пространства имен Forms.Design). Какой бы подход ни предлагался в качестве решения, он также должен работать, когда мой элемент управления добавляется в набор инструментов Visual Studio и когда мой элемент управления помещается на поверхность WinForm в режиме разработки в среде Visual Studio IDE.

Вот что я пытаюсь сделать: В режиме разработки экземпляр элемента управления TableLayoutPanel на форме отображает украшение, которое при щелчке представляет панель «Смарт-тег», состоящую из «действий», таких как «Добавить столбец», «Добавить строку» и т. Д. (Некоторые из этих действий также отображаются в виде глаголов в сетка свойств - я знаю, как изменить эти глаголы: мой вопрос касается только списка действий со смарт-тегами.)

Я хочу изменить список действий смарт-тега времени разработки элемента управления TableLayoutPanel на некоторые из моих собственных элементов.

К сожалению, похоже, что для этого необходимо связать элемент управления с пользовательским конструктором. Тем не менее, я не хочу использовать собственный конструктор или тот, который создан на основе ControlDesigner. Я обнаружил, что при этом я теряю все функциональные возможности дизайнера, предлагаемые элементом управления TableLayoutPanel, такие как просмотр новых строк, столбцов и возможность перетаскивать элементы управления на его поверхность клиента. Я должен сохранить такие визуальные функции времени разработки TableLayoutPanel.

Если я использую атрибут Designer для указания класса TableLayoutPanelDesigner в качестве дизайнера, то мне не повезет, потому что этот класс помечен как внутренний (https://referencesource.microsoft.com/#System.Design/System/Windows/Forms/Design/TableLayoutPanelDesigner.cs).

Как использовать существующий конструктор для элемента управления WinForm TableLayoutPanel, а также настраивать список действий его смарт-тега? Конечно, это должно быть доступно с помощью отражения (но я не мог понять, как).

1 Ответ

0 голосов
/ 18 января 2019

TableLayoutPanelDesiner является внутренним и имеет зависимости от других внутренних классов, и вы не можете наследовать от него. Кроме того, не стоит создавать новый дизайнер элементов управления для TableLayoutPanel с нуля, потому что вы потеряете все текущие функциональные возможности дизайнера.

Действительно хороший трюк - найти дизайнера и манипулировать дизайнером во время разработки. Посмотрите на Сделайте что-нибудь! и Back Color новые предметы:

enter image description here

Для этого вы можете найти дизайнера вашего TableLayoutPanel во время разработки и манипулировать им. Хороший момент в методе OnHandleCreated. Вы можете получить экземпляр IDesignerHost из Site элемента управления, а затем получить конструктор.

Затем вы можете получить текущий список действий для элемента управления, создать новый список действий, содержащий все эти элементы действий, и добавить некоторые новые элементы действий в список.

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