C# 列表<;按钮>;作为财产。不向面板添加按钮

C# 列表<;按钮>;作为财产。不向面板添加按钮,c#,winforms,C#,Winforms,我正在尝试创建一个自定义面板,在其中我可以使用properties->Buttons->[(集合)…]更改属性: 以下是我尝试过的 public class CustomPanel : Panel { private List<Button> buttons = new List<Button>(); public List<Button> Buttons { get { return buttons; }

我正在尝试创建一个自定义面板,在其中我可以使用properties->Buttons->[(集合)…]更改属性:

以下是我尝试过的

public class CustomPanel : Panel
{
    private List<Button> buttons = new List<Button>();

    public List<Button> Buttons
    {
        get { return buttons; }
        set 
        {
             buttons = value;
             this.Controls.Clear();
                
             foreach (var button in buttons)
             {
                button.Size = new Size(200, 30);
                this.Controls.Add(button);
             }
         }
    }
}
公共类自定义面板:面板
{
私有列表按钮=新建列表();
公共列表按钮
{
获取{返回按钮;}
设置
{
按钮=值;
this.Controls.Clear();
foreach(按钮中的var按钮)
{
按钮尺寸=新尺寸(200,30);
此.Controls.Add(按钮);
}
}
}
}

但是,当我使用Properties->Buttons->[(Collection)…]添加新按钮时:它不会将其添加到我的面板。

假设已将
CustomPanel
类添加为自定义控件,并且其基类更改为
panel
,您可以尝试以下代码

using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Design;
using System.Linq;
using System.Windows.Forms;

namespace TEST
{
    public partial class CustomPanel : Panel
    {
        public CustomPanel()
        {
            InitializeComponent();
        }

        [Editor(typeof(ArrayEditor), typeof(UITypeEditor))]
        public Button[] Buttons
        {
            get { return this.Controls.OfType<Button>().ToArray(); }
            set
            {
                SuspendLayout();
                try
                {
                    this.Controls.Clear();

                    foreach (var button in value)
                    {
                        button.Size = new Size(200, 30);
                        this.Controls.Add(button);
                    }
                }
                finally { ResumeLayout(); }
            }
        }
    }
}
使用System.ComponentModel;
使用System.ComponentModel.Design;
使用系统图;
使用系统、绘图、设计;
使用System.Linq;
使用System.Windows.Forms;
名称空间测试
{
公共部分类CustomPanel:面板
{
公众谘询委员会(
{
初始化组件();
}
[编辑器(typeof(ArrayEditor)、typeof(UITypeEditor))]
公共按钮[]按钮
{
获取{返回this.Controls.OfType().ToArray();}
设置
{
SuspendLayout();
尝试
{
this.Controls.Clear();
foreach(值中的var按钮)
{
按钮尺寸=新尺寸(200,30);
此.Controls.Add(按钮);
}
}
最后{ResumeLayout();}
}
}
}
}
确保该项目引用了
System.Design.dll
,以便识别
ArrayEditor

请记住:

  • 设计器通过
    Buttons
    属性添加的每个
    按钮
    控件都将被序列化,就像以常规设计方式添加一样
  • 添加其他(非
    按钮
    )控件仍然可以采用通常的设计方式或编程方式
  • this.Controls.Clear
    将删除任何控件,即使是不使用
    按钮添加的控件
    ;如果要保留这些按钮,可以删除此说明,但需要一种方法来识别以前存在的按钮,并根据需要替换或保留它们
  • 任何
    按钮
    对象的所有属性都可以在
    阵列编辑器
    表单中编辑
  • 您需要处理
    按钮
    控件(新添加和现有控件)的定位,以避免重叠
我建议使用child
FlowLayoutPanel
自动定位按钮,并防止任何人直接干扰按钮集合。使用这种方法,
this.Controls
将成为
flowLayoutPanel1.Controls
(或类似)。
否则,您应该覆盖
OnControlAdded
OnControlRemoved
,以便在添加或删除任何控件时收到通知。

您也应该以某种方式设置位置!请注意,属性的setter仅在为其指定列表对象时触发,而不是在向该列表添加项时触发。我不太清楚你所说的
Properties->Items->[(Collection)…]是什么意思。@TaW我可以这样做,但它不会进入我的列表。你的代码没有按预期工作,因为
list
本身就是一个集合,而
Panel.Controls
是一个完全不同的集合!!每次修改其中一个时,您应该需要在两个方向上同步它们,但是
List
不允许这种行为。也许将
列表
更改为
按钮[]
可以解决问题或提供帮助。您应该重新考虑这种方法的目标:您是否需要一组只包含
按钮的控件,因为您想过滤掉任何其他类型的
控件,或者。。。您只想将
按钮
控件添加到面板?@TaW请注意,问题可能发生在设计器的“属性”窗口中,除非运行开发环境的第二个实例(Visual Studio?)并将其调试器附加到运行设计器的实例,否则无法进行调试。真正的调试器的一种替代方法是通过在整个代码中添加显式指令来记录/显示消息(MessageBox.Show、Console.WriteLine或自定义替代方法)。