C# 是否可以将同一个Windows窗体控件实例添加到多个容器中? 我正在努力实现的目标:

C# 是否可以将同一个Windows窗体控件实例添加到多个容器中? 我正在努力实现的目标:,c#,winforms,C#,Winforms,我有一个有多个页面的向导。在每个页面上,我都需要一个ToolStripDropDownButton,每个都有完全相同的功能和UI。在显示任何页面之前,将创建整个向导和所有页面。ToolStripDropDownButton显示在页面边界内。当用户在一个页面上更改ToolStripDropDownButton的值时,应该在其他页面上更新它 我试图避免的替代解决方案是: 在每个页面上都有一个单独的控件实例,该实例订阅了当任何其他控件的值更改时触发的事件。除了它的复杂性之外,这个解决方案没有什么错 我

我有一个有多个页面的向导。在每个页面上,我都需要一个ToolStripDropDownButton,每个都有完全相同的功能和UI。在显示任何页面之前,将创建整个向导和所有页面。ToolStripDropDownButton显示在页面边界内。当用户在一个页面上更改ToolStripDropDownButton的值时,应该在其他页面上更新它

我试图避免的替代解决方案是: 在每个页面上都有一个单独的控件实例,该实例订阅了当任何其他控件的值更改时触发的事件。除了它的复杂性之外,这个解决方案没有什么错

我所尝试的: 我创建了ToolStripDropDownButton作为向导页面类的静态成员,在第一次请求时对其进行实例化,并在创建页面时向每个页面添加相同的对象。这导致ToolStripDropDownButton没有出现在任何页面上(可能是因为我将它添加到了多个控件中,Winforms不知道如何处理它)


如果无法将同一个控件实例添加到多个容器中,是否有比引发和订阅事件更好的方法来完成此任务?

例如,您可以使用一些数据对象扩展
ToolStripDropDownButton
,然后使用不同的父对象创建多个
ToolStripDropDownButton
实例,然后将它们连接到同一数据对象,并使用该数据对象使
ToolStripDropDownButton
实例保持同步,例如:

public class MyToolStripDropDownButton : ToolStripDropDownButton
{
    public MyData Data { get; private set; }
    public MyToolStripDropDownButton():base()
    {
        this.Text = "Options";
    }

    public void Initialize(MyData data)
    {
        this.Data = data;
        this.Data.ElementsToNotify.Add(this);
        foreach (string option in this.Data.Options.Keys)
        {
            ToolStripMenuItem item = new ToolStripMenuItem(option);
            item.CheckOnClick = true;
            item.CheckedChanged += new EventHandler(item_CheckedChanged);
            this.DropDownItems.Add(item);
        }
    }

    void item_CheckedChanged(object sender, EventArgs e)
    {
        ToolStripMenuItem item = (ToolStripMenuItem)sender;
        this.Data.OnSelectOption(item.Text, item.Checked);
    }

}

public class MyData
{
    public List<MyToolStripDropDownButton> ElementsToNotify { get; private set; }
    public Dictionary<string, bool> Options { get; private set; }

    public MyData()
    {
        this.Options = new Dictionary<string, bool>();
        this.ElementsToNotify = new List<MyToolStripDropDownButton>();
    }

    public void OnSelectOption(string option, bool isChecked)
    {
        Options[option]=isChecked;

        foreach (MyToolStripDropDownButton btn in ElementsToNotify)
        {
            foreach(ToolStripMenuItem  item in btn.DropDownItems.OfType<ToolStripMenuItem>())
            {
                item.Checked = Options[item.Text];
            }

        }
    }
}

您无法执行所需的操作,控件只能有一个父控件


解决方法是:在每个页面的VisibleChanged事件中将控件从一个页面移动到下一个页面。从用户的角度来看,该控件存在于每个页面上,但实际上,当它变为可见时,它将被移动到“当前”页面。

您不能将一个控件添加到多个容器中。您不能,您只能通知您的朋友也要更改。为什么要进行否决投票?这是我第一次发布问题,我想知道下一次如何做得更好。我认为这个问题很好,也许可以粘贴一些有效的解决方案代码,但您不喜欢它,因此,我们可以提示如何改进它,并提供一个片段,显示您如何尝试将同一控件添加到多个容器中,以及显示了哪些错误。No。一个控件只能有一个父控件。解决方法是:在每个页面的VisibleChanged事件中将控件从一个页面移动到下一个页面。从用户的角度来看,控件存在于每个页面上,但实际上,当控件变为可见时,它将被移动到“当前”页面。
        MyData data = new MyData();
        data.Options.Add("A", false);
        data.Options.Add("B", false);
        data.Options.Add("C", false);

        MyToolStripDropDownButton mb1 = new MyToolStripDropDownButton();
        mb1.Initialize(data);

        MyToolStripDropDownButton mb2 = new MyToolStripDropDownButton();
        mb2.Initialize(data);

        toolStrip1.Items.Add(mb1);
        toolStrip2.Items.Add(mb2);