我想我有一个解决方案。问题不在于您无法创建句柄。您只需访问控件上的 Handle get 访问器即可做到这一点。问题是 WinForms 不会创建该控件,因为它不可见。事实证明,在幕后,System.Windows.Forms.Control
有两个重载CreateControl
。第一个是公共的,不带任何参数,它调用第二个internal
这需要一个boolean
参数:ignoreVisible,顾名思义,它允许调用代码创建控件,即使它不可见。这CreateControl
不带参数的方法将 false 传递给此内部方法,这意味着如果控件不可见,则不会创建它。所以,技巧就是使用Reflection来调用内部方法。首先,我创建了两种创建控件的方法:
private static void CreateControls( Control control )
{
CreateControl( control );
foreach ( Control subcontrol in control.Controls )
{
CreateControl( subcontrol );
}
}
private static void CreateControl( Control control )
{
var method = control.GetType().GetMethod( "CreateControl", BindingFlags.Instance | BindingFlags.NonPublic );
var parameters = method.GetParameters();
Debug.Assert( parameters.Length == 1, "Looking only for the method with a single parameter" );
Debug.Assert( parameters[0].ParameterType == typeof ( bool ), "Single parameter is not of type boolean" );
method.Invoke( control, new object[] { true } );
}
现在,我们添加一个调用CreateControls
对于第二个选项卡:
public Form1()
{
InitializeComponent();
boolList.Add( false );
bs.DataSource = boolList;
checkBox1.DataBindings.Add( "Checked", bs, "" );
this.button1.Click += this.button1_Click;
this.checkBox1.CheckedChanged += this.checkBox1_CheckedChanged;
CreateControls( this.tabPage2 );
}
此外,我添加了一些调试消息,以便我可以查看事件是否已触发:
private void button1_Click( object sender, EventArgs e )
{
Debug.WriteLine( "button1_Click" );
updating = true;
boolList[0] = true;
bs.ResetBindings( false );
Application.DoEvents();
updating = false;
}
private void checkBox1_CheckedChanged( object sender, EventArgs e )
{
Debug.WriteLine( "checkBox1_CheckedChanged" );
if ( !updating )
{
Debug.WriteLine( "!updating" );
MessageBox.Show( "CheckChanged fired outside of updating" );
}
}
现在,无论您是否导航到第二个选项卡,单击第一个选项卡上的按钮都会触发checkbox1_Changed
事件程序。鉴于您提供的设计,如果您单击该按钮,它将不会显示 MessageBox,因为updating
将会是真的。但是,那Debug.WriteLine
将在输出窗口中显示它已触发。