好的,我又来了一个怪人。
我有一个正在运行的项目,其中我在构建一棵给定形式的控件/组件树,并使用该树生成指向其中任何一个的最短唯一路径。只是作为实际问题的背景。
现在我在处理TabControl方面经历了一段很糟糕的时光,在许多级别上,它的完成情况都非常糟糕,但是大多数可以通过WinAPI调用来解决。精细。现在我有一个问题,即使查看Microsoft参考代码库也无法解决。
由于某些未知原因,TabControl会在选择选项卡时根据ControlCollection重新排序。从一个微型测试应用程序来看,它似乎比我最初预期的要随机得多。不幸的是,这打破了我的后备方法来处理未命名的控件,并且稳定的索引编制对我来说非常重要。
using System;
using System.Windows.Forms;
namespace TabControlOrderTest
{
using System.Threading;
using System.Threading.Tasks;
public partial class Form1 : Form
{
private TabControl tabControl1;
private ListBox listBox1;
public Form1()
{
this.tabControl1 = new TabControl();
this.listBox1 = new ListBox();
this.InitializeComponent();
this.SuspendLayout();
//
// tabControl1
//
this.tabControl1.Location = new System.Drawing.Point(12, 12);
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(566, 244);
this.tabControl1.TabIndex = 0;
this.tabControl1.SelectedIndexChanged += new EventHandler(this.tabControl1_SelectedIndexChanged);
//
// listBox1
//
this.listBox1.FormattingEnabled = true;
this.listBox1.Location = new System.Drawing.Point(658, 34);
this.listBox1.Name = "listBox1";
this.listBox1.Size = new System.Drawing.Size(130, 251);
this.listBox1.TabIndex = 2;
this.Controls.Add(this.listBox1);
this.Controls.Add(this.tabControl1);
this.ResumeLayout(false);
for (var i = 0; i < 10; i++)
{
this.tabControl1.TabPages.Add(
new TabPage($"tabPage{i}")
{
Name = $"tabPage{i}"
});
}
}
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
Task.Run(
() =>
{
for (var i = 9; i >= 0; i--)
{
Thread.Sleep(500);
this.tabControl1.SelectedIndex = i;
}
});
}
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
var pages = this.tabControl1.TabPages;
var controls = this.tabControl1.Controls;
this.Text = $"{pages.Count};{controls.Count}";
this.listBox1.Items.Clear();
for (int i = 0, count = this.tabControl1.TabCount; i < count; i++)
{
if (ReferenceEquals(pages[i], controls[i]))
{
continue;
}
this.listBox1.Items.Add($"{pages[i].Name} != {controls[i].Name}");
}
}
}
}
有时候它非常稳定,有时每次点击都会变得更加混乱。有人可以给我提示为什么会这样吗?我会很感激任何线索。
编辑:我要问的是Controls属性,因为这是Controls存储所有基础项的通用位置。我可以将生产代码专门切换到TabControl的TabPageCollection上,但是它可能会破坏修复以外的功能,所以这就是我试图了解其行为的原因。
答案 0 :(得分:0)
好的,我已经找到了原因。
这由Control.UpdateChildControlIndex(Control ctl)完成,在处理WmWindowPosChanged时会调用
https://referencesource.microsoft.com/System.Windows.Forms/R/13dbf65f74593e7c.html
从第一行可以明显看出,可以选择禁用它。
.NET 4.6之前有点痛苦(因为它需要最丑陋的反射代码才能做到)。 从4.6开始,您只需致电
AppContext.SetSwitch("Switch.System.Windows.Forms.AllowUpdateChildControlIndexForTabControls", false);
还有利润。希望如此。
就我而言,我不喜欢为我的编码UI测试切换.NET FW的某些内部状态的想法,所以我将切换到TabControl的其他控件集合,正如我在问题中提到的那样。但是很高兴知道为什么要这么做。