You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义控件中实现编辑器内可用按钮功能遇难题

实现自定义控件的编辑器内添加/删除图层按钮

你看到TabControl的“添加选项卡”“删除选项卡”按钮属于设计器扩展功能,是通过自定义控件设计器实现的,而非控件本身的运行时逻辑。以下是具体实现步骤和代码示例:

核心思路

通过为自定义控件绑定专属设计器,在设计器中添加DesignerActionList来定义编辑器内的操作选项,关联控件的添加/删除图层方法,实现和TabControl类似的编辑器交互。

代码实现

1. 自定义图层面板控件

using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;

// 绑定自定义设计器
[Designer(typeof(LayerPanelDesigner))]
public class LayerPanel : Panel
{
    // 存储图层集合
    private List<Control> _layers = new List<Control>();

    // 公开图层集合供设计器访问
    public List<Control> Layers
    {
        get => _layers;
        set => _layers = value;
    }

    // 内部添加图层逻辑
    public void AddLayer()
    {
        var newLayer = new Panel()
        {
            Name = $"Layer{_layers.Count + 1}",
            Size = this.Size,
            Location = Point.Empty,
            BorderStyle = BorderStyle.FixedSingle
        };
        _layers.Add(newLayer);
        Controls.Add(newLayer);
        Invalidate();
    }

    // 内部删除图层逻辑
    public void RemoveLayer()
    {
        if (_layers.Count == 0) return;
        
        var targetLayer = _layers[^1];
        _layers.Remove(targetLayer);
        Controls.Remove(targetLayer);
        targetLayer.Dispose();
        Invalidate();
    }
}

2. 自定义控件设计器

public class LayerPanelDesigner : ContainerControlDesigner
{
    private DesignerActionListCollection _actionLists;

    // 重写ActionLists属性,返回自定义操作列表
    public override DesignerActionListCollection ActionLists
    {
        get
        {
            if (_actionLists == null)
            {
                _actionLists = new DesignerActionListCollection();
                _actionLists.Add(new LayerPanelActionList(Component));
            }
            return _actionLists;
        }
    }
}

// 定义设计器操作项列表
public class LayerPanelActionList : DesignerActionList
{
    private readonly LayerPanel _targetPanel;

    public LayerPanelActionList(IComponent component) : base(component)
    {
        _targetPanel = component as LayerPanel;
    }

    // 返回要显示的操作项
    public override DesignerActionItemCollection GetSortedActionItems()
    {
        var actionItems = new DesignerActionItemCollection();
        // 添加"添加图层"操作,关联对应方法
        actionItems.Add(new DesignerActionMethodItem(this, nameof(TriggerAddLayer), "添加图层", true));
        // 添加"删除图层"操作,关联对应方法
        actionItems.Add(new DesignerActionMethodItem(this, nameof(TriggerRemoveLayer), "删除图层", true));
        return actionItems;
    }

    // 触发控件的添加图层方法,并通知设计器刷新
    public void TriggerAddLayer()
    {
        _targetPanel.AddLayer();
        var designerHost = GetService(typeof(IDesignerHost));
        designerHost?.GetType().InvokeMember("Refresh", System.Reflection.BindingFlags.InvokeMethod, null, designerHost, null);
    }

    // 触发控件的删除图层方法,并通知设计器刷新
    public void TriggerRemoveLayer()
    {
        _targetPanel.RemoveLayer();
        var designerHost = GetService(typeof(IDesignerHost));
        designerHost?.GetType().InvokeMember("Refresh", System.Reflection.BindingFlags.InvokeMethod, null, designerHost, null);
    }
}

注意事项

  • 项目需引用System.Design.dll(在VS的项目引用→框架程序集中查找)
  • 设计器相关代码可放在单独文件中,或用#if DEBUG包裹,避免发布时引入不必要的设计器依赖
  • 如果你的“图层”是自定义类而非Control,只需调整Layers集合的类型和AddLayer/RemoveLayer的内部逻辑即可

内容的提问来源于stack exchange,提问作者WasdNot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 17:13:23