我有一个标签式界面 - 标签将包含多个嵌套控件。特别是,面板包含面板,包含网格等。甚至在某些情况下还有其他Tab控件。 (是的,它可能有点凌乱)
但是,现在我需要在运行时动态创建其中一些选项卡 - 并且仍然引用它们上的控件。所以 - 例如,假设我有类似
的东西
标签
面板
的TabControl
标签
网格
图形/图
面板
按钮
我需要为我需要显示的每个结果DataTable创建多个新选项卡(我不知道有多少我必须在运行时创建 - 或者我只是在设计时完成这一切)。
我知道我将在RunTime创建这些控件 - 我可以轻松地为另外一个实例创建 - 但后来我开始遇到命名问题。我不能将三个GridControls(全部称为DataGrid)添加到同一个表单中 - 因为C#是强类型的,所以我无法在运行时创建变量名称。而且我还需要能够在某些时候引用这些控件。
所以 - 我正在寻找可能的解决方案。我可以为我希望创建的每种控件创建数组。每个选项卡有超过15个控件(一些嵌套) - 所以它可能会有点混乱。但是它允许我访问每个控件 - 因为我可以使用Tab页面的Tag属性来允许我访问各种数组。如果我创建的数组最多可容纳50个元素 - 它应该足够了(我没有看到用户创建超过5或10个这些额外选项卡)。
由于我对C#和Visual Studio有点新手 - 我想知道其他人如何处理这类任务?你将如何在表单上创建嵌入式(嵌套)控件的多个实例 - 知道你必须在代码的其他地方引用它们?
任何想法和指示都会非常感激。
谢谢
布拉德利
答案 0 :(得分:0)
由于有任意数量的标签页,您需要以编程方式管理它们。
所以 - 我正在寻找可能的解决方案。我可以为我希望创建的每种控件创建数组。每个选项卡有超过15个控件(一些嵌套) - 所以它可能会有点混乱。但是它允许我访问每个控件 - 因为我可以使用Tab页面的Tag属性来允许我访问各种数组。如果我创建了最多包含50个元素的数组 - 它应该足够了(我没有看到用户创建超过5或10个额外选项卡)。
这确实会变得混乱,并且是一个错误的秘诀。 Tag
在适当的情况下是一个非常有用的属性,但通常你应该避免使用它,除非你有充分的理由。您可能会无意中引入泄漏内存的循环引用。我发现它最适合存储相关的元数据,例如ID(但是,避免在其中存储值类型,因为它们变为boxed)。
如果您还没有,我建议您使用与您在设计器中设置的名称的变量一样的命名约定。由于支持变量反映了这些名称,因此它可以帮助您避免与属性发生名称冲突,并使代码更加一致。我和我的团队使用约定mSomeField
来获取私有字段和设计器集名称,这使我们在多年来避免了大多数名称冲突方面做得很好。
首先设计一个新的UserControl
,它将作为最常见标签类别的内容,添加尽可能多的常见布局。为每个其他标签类别设计额外的UserControl
。为您需要公开的每个嵌套控件添加访问器。
请注意,以下代码使用了一些C#6/7功能。
在实践中,这可能是这样的:
// Code-behind for the UserControl representing the content of the 1st tab category.
class Cat1TabContent : UserControl
{
//...
// These all refer to controls created and named from the designer.
public Panel PrimaryPanel => primaryPanel;
public TabControl TabManager => tabManager;
public Panel SecondaryPanel => secondaryPanel;
//...
}
管理标签(在主窗体和具有TabControl的所有其他控件中):
//...
private List<UserControl> tabContents = new List<UserControl>();
void AddTab<T>() where T : UserControl, new()
{
var tab = new TabPage();
var tabContent = new T();
tabContents.Add(tabContent);
tab.Controls.Add(tabContent);
tabControl.Controls.Add(tab);
}
void RemoveTab(TabPage tab)
{
if (tab == null) throw new ArgumentNullException(nameof(tab));
if (tab.Controls.Count != 0 && tab.Controls[0] is UserControl tabContent) {
tabContents.Remove(tabContent);
}
tabControl.Controls.Remove(tab);
}
//...
访问嵌套控件:
// Form >> Tab Control >> 1st Tab >> 1st Child.
// This assumes AddTab<Cat1Content>() was called.
var firstContent = (Cat1Content)tabContents[0];
// Content >> PrimaryPanel; Enumerates over nested controls.
foreach (var child in firstContent.PrimaryPanel.Controls) {
// ...
}
// Content >> Tab Control; Enumerates over nested tabs.
foreach (var child in firstContent.TabManager.Controls) {
// This is safe, TabControl throws an exception if you try to add anything that isn't a TabPage.
var tab = (TabPage)child;
// ...
}