星期日, 7月 03, 2022

[C#] ParentControlDesigner

一直以為 UserControl 就必須事先把控件設計好,整個 UserControl 拉進來使用就是,在閱讀官方文件 - Use Visual C# to make a UserControl object act as a control container design-time 後,發現原來在設計階段 (design mode) 下可以讓 UserControl 變成父容器,能把控件拖曳進去變成子控件

ParentControlDesigner 是從 ControlDesigner 繼承而來,所以除了讓 UserControl 在設計階段變成容器外,也同樣可以設計智能標籤來使用喔

設計智能標籤內容

只設計一個背景顏色屬性來使用
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;

namespace UCParentControlDesigner
{
    public class UCContainerActionList : DesignerActionList
    {
        private UCContainer _ucContainer;

        public UCContainerActionList(IComponent component) : base(component)
        {
            _ucContainer = component as UCContainer;
        }

        private PropertyDescriptor GetPropertyByName(string propName)
        {
            PropertyDescriptor prop = TypeDescriptor.GetProperties(_ucContainer)[propName];
            if (null == prop)
                throw new ArgumentException($"UCContainer 屬性:{propName} 沒有找到");
            else
                return prop;
        }

        public Color BackColor
        {
            get
            {
                return _ucContainer.BackColor;
            }
            set
            {
                GetPropertyByName(nameof(BackColor)).SetValue(_ucContainer, value);
            }
        }

        public override DesignerActionItemCollection GetSortedActionItems()
        {
            DesignerActionItemCollection items = new DesignerActionItemCollection();

            items.Add(new DesignerActionPropertyItem(
                 nameof(BackColor),
                 "背景顏色",
                 "外觀",
                 "選擇背景顏色"));

            return items;
        }
    }
}

使用 ParentControlDesigner

UCContainerControlDesigner 繼承 ParentControlDesigner,使 UserControl 變成父容器並把上述設計好的智能標籤放進來
using System.ComponentModel.Design;
using System.Windows.Forms.Design;

namespace UCParentControlDesigner
{
    public class UCContainerControlDesigner : ParentControlDesigner
    {
        private DesignerActionListCollection actionLists;

        public override DesignerActionListCollection ActionLists
        {
            get
            {
                if (null == actionLists)
                {
                    actionLists = new DesignerActionListCollection();
                    actionLists.Add(new UCContainerActionList(this.Component));
                }
                return actionLists;
            }
        }
    }
}

設計階段具容器功能的 UserControl

建立 UCContainer UserControl 並使用 UCContainerControlDesigner
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace UCParentControlDesigner
{

    [Designer(typeof(UCContainerControlDesigner))]
    public partial class UCContainer : UserControl
    {
        public UCContainer()
        {
            InitializeComponent();

            // 預設背景顏色為淡灰色
            BackColor = Color.LightGray;
        }
    }
}

設計效果顯示

該 gif 示範把 Button 控件拖曳進 UCContainer 內,並成為 UCContainer 的子控件
背景顏色的智能標籤

沒有留言:

張貼留言