Visual Studio - TabControl.TabPages.Insert无效

vIc*_*erg 20 c# tabcontrol tabpage winforms

这是我的代码:

    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();    
    }
Run Code Online (Sandbox Code Playgroud)

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

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

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

如果我做这个改变:

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

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

使用Insert方法有什么我不理解的东西吗?它为什么工作?

tan*_*ius 43

关于social.msdn有一个评论- 虽然我在文档中找不到这样的东西:

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

试试上面提到的代码

IntPtr h = this.tabControl1.Handle;
Run Code Online (Sandbox Code Playgroud)

在循环服务之前

  • 我无法相信它是如此愚蠢...无论如何它正在发挥作用! (2认同)
  • 可能会更简洁一些: `tabControl1.CreateControl();` 这将摆脱虚拟变量 `h` 和可能还有代码分析警告。PS:令人惊讶的是,5 岁的 SO 问题和答案今天仍然适用。;-) (2认同)
  • @Tobias,我只是尝试使用 `.CreateControl()` 而不是 `.Handle` 但它不起作用。新页面仍未插入。 (2认同)

Rez*_*aei 6

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

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

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

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

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

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

  • 您可以调用插入OnShown方法或表单的Shown事件处理程序。
  • 您还可以Show在插入标签页之前调用表单的方法。
  • 您可以将配置列表及其Add控制反转。
  • 您可以将所有选项卡页添加到一个数组中,反转该数组并使用AddRange.