26

这是我的代码:

    public MainForm()
    {
        InitializeComponent();

        MyServiceSettings obj = (MyServiceSettings)ConfigurationManager.GetSection("MyServiceSettings");

        foreach (MyServiceConfigElement service in obj.Services)
            CreateServiceControl(service);
    }

    private void CreateServiceControl(MyServiceConfigElement service)
    {
        TabPage tp = new TabPage(service.Name);
        tabControl1.TabPages.Insert(0, tp);
        //tabControl1.TabPages.Add(tp);
        tabControl1.Refresh();    
    }

简而言之,它读取配置文件中的一个部分,并为该部分中的每个元素创建一个选项卡。

我已经在设计时创建了一个静态 TabPage。我希望在此静态选项卡之前插入动态创建的选项卡。

运行此代码,tabcontrol 仅显示静态标签页。

如果我做这个改变:

        private void CreateServiceControl(SoftInfoServiceConfigElement service)
    {
        TabPage tp = new TabPage(service.Name);
        //tabControl1.TabPages.Insert(1, tp);
        tabControl1.TabPages.Add(tp);
        tabControl1.Refresh();
    }

使用 Add 方法显示所有页面。但我没有得到我想要的订单。

Insert 方法有什么我不明白的地方吗?为什么它不起作用?

4

3 回答 3

49

social.msdn上有一条评论——尽管我在文档中找不到类似的内容:

必须创建 TabControl 的句柄才能使 Insert 方法工作

尝试提到的代码

IntPtr h = this.tabControl1.Handle;

在你循环你的服务之前

于 2009-10-07T15:48:09.990 回答
1

您将相同的索引传递给该Insert()方法。如果你想简单地增加,这应该工作:

// ...

int i = 0;
foreach (MyServiceConfigElement service in obj.Services)
            CreateServiceControl(service, i++);

// ...

private void CreateServiceControl(MyServiceConfigElement service, int i)
{
        TabPage tp = new TabPage(service.Name);
                tabControl1.TabPages.Insert(i, tp);
// ...

}
于 2009-10-07T16:01:31.713 回答
1

由于“布拉德正在寻找一个规范的答案”,我专注于回答 OP 的问题:“插入方法有什么我不明白的地方吗?为什么它不起作用? ”。

这是一个错误。 如果未创建 TabControl 句柄,则该Insert方法不起作用;但是Add,无论是否创建句柄,该方法始终按预期工作。通过正确的实施可以避免这种情况。

这就是 .NET Tab 控件的工作方式:它是基于本机TabControl创建的,它显示选项卡标题列表并提供显示区域以显示控件内部的一些内容。.NET 实现负责将这些标题添加到本机控件,并保留容器列表 (TabPages) 并正确定位它们并在用户选择选项卡时显示它们。

错误是如何发生在 Insert 方法而不是 Add 方法的? 如果 .NET 实现不使用本地方法将标签页添加到本地 TabControl,那么它不会显示标题;这就是这里发生的情况:
Insert方法中,当未创建句柄时,.NET 代码不会调用本机方法将标签页添加到本机控件。方法相同Add;但是Add,无论是否创建了句柄,该方法始终按预期工作,因为在该Add方法中,.NET 代码检查是否未创建控制句柄,然后将标签页添加到页面列表中,然后稍后创建控制句柄时, 是调用集合中所有页面的原生 API 方法;但是对于Insert方法,当没有创建句柄时,他们还没有将标签页添加到标签页列表中。

如果您想自己跟踪代码,请查看InsertAdd的源代码,还可以考虑查看TabControl的ControlCollection的自定义实现,特别是它的Add方法,并注意InsertingItemIsHandleCreated属性。

最后,如何避免这种情况?好吧,接受的答案可以正常工作,但是如果您不喜欢使用虚拟代码行来获取控件的句柄,则可以执行以下任一操作:

  • OnShown您可以在表单的方法或Shown事件处理程序中调用插入。
  • 您也可以Show在插入标签页之前调用表单的方法。
  • 您可以将配置列表和Add它们反转到控件。
  • 您可以将所有标签页添加到数组中,反转数组并使用AddRange.
于 2021-12-26T12:20:35.610 回答