是否可以将同一个Windows窗体控件实例添加到多个容器中?

时间:2017-03-08 13:43:29

标签: c# winforms

我想要完成的任务:

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

我试图避免的替代解决方案:

在每个页面上有一个单独的控件实例,该实例订阅了在更改任何其他控件的值时触发的事件。除了它的复杂性之外,这个解决方案没有任何问题。

我尝试过:

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

如果无法将相同的控件实例添加到多个容器中,是否有更好的方法来完成任务而不是提升和订阅事件?

2 个答案:

答案 0 :(得分:1)

你无法做你想做的事,控制只能有1个父母。

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

答案 1 :(得分:0)

例如,您可以使用某个数据对象扩展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];
            }

        }
    }
}

// .......................

        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);