对于初学者,我会使用Collection<Control>
而不是List<T>
. 列表通常会起作用,但它确实会以您可能不想要的方式公开您的收藏。
要获取现有控件,您需要深入context.Container.Components
研究LoadValues
覆盖。它将包含所有内容,包括主机表单本身和组件,因此您可能必须过滤它们。可以确定的一件事是删除组件(如DataGridViewColumns
和TabPages
),因为它们不会进入控件列表或集合;其他东西,比如 TableLayoutPanels,你也经常想要删除。
此版本为默认下拉列表过滤掉一些组件和控件:
protected override void LoadValues(System.ComponentModel.ITypeDescriptorContext context, System.IServiceProvider provider, object value)
{
bool bAdd = true;
Control thisCtl = null;
Collection<Control> tCollection = (Collection<Control>)value;
foreach (object obj in context.Container.Components) {
//Cycle through the components owned by the form in the designer
bAdd = true;
// exclude other components - this weeds out DataGridViewColumns which
// can only be used by a DataGridView
if (obj is Control) {
thisCtl = (Control)obj;
if (ExcludeForm) {
bAdd = !(thisCtl is Form);
}
// custom exclude list
if ((typeExclude != null) && (typeExclude.Count > 0)) {
if (typeExclude.Contains(thisCtl.GetType)) {
bAdd = false;
}
}
bool bCheck = false;
int ndx = 0;
if (bAdd) {
bCheck = tCollection.Contains(thisCtl);
ndx = myCtl.Items.Add(new ListItem(thisCtl));
myCtl.SetItemChecked(ndx, bCheck);
}
}
}
}
如果您愿意,可以显示符合条件的控件对话框样式并使用 CheckedListBox 供用户选择控件。有一篇关于 CodeProject Selecting Form's Controls at Design Time的文章进行了更详细的介绍。
它在 VB 中,但可以让您轻松实现这样的野兽(我写了它,所以我可能有偏见):
ExampleDropDownControlCollectionUIEditor : ControlCollectionDropDownUIEditor
{
public ExampleDropDownControlCollectionUIEditor() : base()
{
base.ExcludeForm = true;
base.CheckControlWidth = 200;
base.typeExclude.Add(typeof(RadioButton));
base.typeExclude.Add(typeof(Label));
}
}
对话框形式很简单,只是使用了不同的基类,ControlCollectionDialogUIEditor