C#创建嵌套控件的多个实例

问题描述 投票:0回答:1

我有一个标签式界面 - 标签将包含多个嵌套控件。特别是,面板包含面板,包含网格等。甚至在某些情况下还有其他Tab控件。 (是的它可能有点乱)

但是,现在我需要在运行时动态创建其中一些选项卡 - 并且仍然引用它们上的控件。所以 - 例如,假设我有类似的东西

标签

面板

的TabControl

标签

图/图

面板

纽扣

我需要为我需要显示的每个结果DataTable创建多个新选项卡(我不知道在运行时我必须创建多少个 - 或者我只是在设计时才这样做)。

我知道我将在RunTime创建这些控件 - 我可以轻松地为另外一个实例创建 - 但后来我开始遇到命名问题。我不能将三个GridControls(全部称为DataGrid)添加到同一个表单中 - 因为C#是强类型的,所以我无法在运行时创建变量名称。而且我还需要能够在某些时候引用这些控件。

所以 - 我在寻找可能的解决方案。我可以为我希望创建的每种控件创建数组。每个选项卡有超过15个控件(一些嵌套) - 所以它可能会有点混乱。但是它允许我访问每个控件 - 因为我可以使用Tab页面的Tag属性来允许我访问各种数组。如果我创建的数组最多可容纳50个元素 - 它应该足够了(我没有看到用户创建超过5或10个这些额外选项卡)。

由于我对C#和Visual Studio有点新手 - 我想知道其他人如何处理这类任务?你将如何在表单上创建嵌入式(嵌套)控件的多个实例 - 知道你必须在代码的其他地方引用它们?

任何想法和指示将非常感激。

谢谢

布拉德利

c# winforms controls runtime
1个回答
0
投票

由于有任意数量的选项卡,您需要以编程方式管理它们。

所以 - 我在寻找可能的解决方案。我可以为我希望创建的每种控件创建数组。每个选项卡有超过15个控件(一些嵌套) - 所以它可能会有点混乱。但是它允许我访问每个控件 - 因为我可以使用Tab页面的Tag属性来允许我访问各种数组。如果我创建的数组最多可容纳50个元素 - 它应该足够了(我没有看到用户创建超过5或10个这些额外选项卡)。

这确实会变得混乱,并且是一个错误的秘诀。 Tag在适当的情况下是一个非常有用的属性,但通常你应该避免使用它,除非你有充分的理由。您可能会无意中引入泄漏内存的循环引用。我发现它最适合存储相关元数据,例如ID(但是,避免在其中存储值类型,因为它们变成boxed)。

如果您还没有,我建议采用与您在设计器中设置的名称的变量一起使用的相同命名约定。由于支持变量反映了这些名称,因此它可以帮助您避免与属性发生名称冲突,并使代码更加一致。我的团队和我使用会议mSomeField用于私人领域和设计师集合名称,这使我们在多年来避免了大多数名称冲突。

首先设计一个新的UserControl,它将作为最常见的标签类别的内容,添加尽可能多的常见布局。为每个附加选项卡类别设计额外的UserControls。为需要公开的每个嵌套控件添加访问器。

请注意,以下代码使用了一些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;
    // ...
}
© www.soinside.com 2019 - 2024. All rights reserved.