C# Winforms 设计器:如何在设计时复制和粘贴集合

本文关键字:复制 集合 Winforms | 更新日期: 2023-09-27 18:35:14

>假设我创建了以下自定义控件:

public class BookshelfControl : Control
{
    [Editor(typeof(ArrayEditor), typeof(UITypeEditor)),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public Book[] Books { get; set; }
    ...
}

其中Book是一个简单的自定义类,定义为:

public class Book : Component
{
    public string Author { get; set; }
    public string Genre { get; set; }
    public string Title { get; set; }
}

使用它,我可以轻松地在Visual Studio设计器中编辑Books集合。

但是,如果我创建一个 BookshelfControl 实例,然后在设计器中复制和粘贴,则不会复制Books集合,而是第二个控件引用第一个 contol 集合中的所有项(例如bookshelfControl1.Book[0]等于 bookshelfControl2.Book[0] )。

因此,我的问题是,在设计时复制和粘贴控件实例时,如何告诉 Visual Studio 设计器复制我的Books集合?

C# Winforms 设计器:如何在设计时复制和粘贴集合

经过几个小时的研究,我相信我已经找到了需要做什么,以便指示设计人员在设计时使用复制和粘贴操作复制集合项。

为我的BookshelfControl使用自定义设计器类,我可以重写ComponentDesigner.Associated组件属性。 根据 MSDN 文档:

ComponentDesigner.AssociatedComponents 属性指示在复制、拖动或移动操作期间要与设计器管理的组件一起复制或移动的任何组件。

修改后的类最终为:

[Designer(typeof(BookshelfControl.Designer))]
public class BookshelfControl : Control
{
    internal class Designer : ControlDesigner
    {
        private IComponent component;
        public override void Initialize(IComponent component)
        {
            base.Initialize(component);
            this.component = component;
        }
        //
        // Critical step getting the designer to 'cache' related object
        // instances to be copied with this BookshelfControl instance:
        //
        public override System.Collections.ICollection AssociatedComponents
        {
            get
            {
                return ((BookshelfControl)this.component).Books;
            }
        }
    }
    [Editor(typeof(ArrayEditor), typeof(UITypeEditor)),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public Book[] Books { get; set; }
    ...
}

AssociatedComponents 属性的结果为设计器提供了对象的集合(可以是嵌套控件、其他对象、基元),这些对象被复制到剪贴板以粘贴到其他位置。

在测试中,我确定在设计时发出 copy 命令( CTRL + C)后立即读取 AssociatedComponents 属性。

我希望这可以帮助其他想要节省时间追踪这个相当晦涩的功能的人!

我的回答解决了你的问题,除非你周围有很多东西。您不应该从Component继承Book。只需使用 :

    [Serializable]
    public class Book 
    {
        public string Author { get; set; }
        public string Genre { get; set; }
        public string Title { get; set; }
    }

我测试了它,它工作正常。如果你真的想使用Component,你应该创建一个自定义的编辑器属性类。