我有一个 C# WinForms 'ListboxPanelControl' UserControl,它由一个 SplitContainer 组成,它在左侧的 'Panel1' 中托管一个用户绘制的 Listbox 控件。SplitContainer 的右侧“Panel2”将承载在项目添加到列表框中时添加的面板。因此,如果设计时用户将第一项添加到 Listbox,则关联的 Panel 将添加到 SplitContainer 的“Panel2”。如果将第二个项目添加到列表框,则会将第二个面板添加到 SplitContainer 的“Panel2”。然后,当用户选择 Listbox 项目时,相关的 Panel 会显示在右侧。
问题出现在设计时,当用户将控件(例如按钮)从工具箱拖放到当前活动的右侧面板(与当前选定的列表框项对应的面板)上时。我以编程方式将其添加到适当的 Panel 的 Controls 集合中,但这会导致Microsoft Visual Studio IDE中出现“'child' is not a child control of this parent”错误。
我研究了这个问题并发现了一些有用的文章,显示“如何允许一个控件,它是另一个控件的子控件,在设计时接受将控件放到它上面”,例如: http: //www.codeproject.com/文章/37830/设计嵌套控件
这将“DesignerSerializationVisibility”属性与 ControlDesigner 的“EnableDesignMode”方法结合使用,以允许 VS IDE 处理将控件拖放到另一个控件上。问题在于,在这种情况下,UserControl 的目标宿主 Control 是有效固定的并且预先知道。使用我的控件,可以在设计时将其他控件拖放到其上的目标托管面板是预先未知的,因为我的 UserControl 本身可以“即时”构建(当用户添加更多列表框项目时在更多潜在的托管小组中)。
我尝试过以更灵活的方式使用“DesignerSerializationVisibility”和“EnableDesignMode”方法,但似乎仍然遇到上述“子不是此父级的子控件”错误。
我希望这一切都有意义!?代码目前看起来像这样:
这是在 ListboxPanelControl 类中:...
[
Category("Appearance"),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)
]
public Panel MainPanel
{
get
{
//Instead of returning a 'fixed' Panel we return whatever the currently
//active Panel is according to the currently selected Listbox item
if( mnCurrentlyActiveListBoxIndex >= 0 )
{
ListBoxEntry lEntry = (ListBoxEntry)listBox.Items[mnCurrentlyActiveListBoxIndex];
return lEntry.RelatedPanel;
}
return null;
}
}
然后,在 ListBoxPanelControl 的“OnControlAdded”事件中,我为当前活动的面板调用“EnableDesignMode”(通过简单的“SetDesignMode”包装),然后添加控件:
protected override void OnControlAdded(ControlEventArgs e)
{
...
mDesigner.SetDesignMode(MainPanel, "MainPanel" + mnCurrentlyActiveListBoxIndex.ToString());
ListBoxEntry lEntry = (ListBoxEntry)listBox.Items[mnCurrentlyActiveListBoxIndex];
lEntry.RelatedPanel.Controls.Add(e.Control);
e.Control.BringToFront();
e.Control.Refresh();
...
}
我希望我已经足够清楚地解释了这个问题!基本上,有没有人设法将控件添加到他们的 WinForms UserControl,其中目标托管控件本身就是一个子控件,并且当他们的 UserControl 本身是动态的并且是动态构建的?
感谢您的帮助/见解!托尼。