I think I have a solution. The problem is not that you cannot create a Handle. You can do that by simply accessing the Handle get accessor on the Control. The problem is that WinForms does not create the control because it is not visible. As it turns out, behind the scenes, a System.Windows.Forms.Control
has two overloads for CreateControl
. The first, which is public, takes no parameters and it calls the second which is internal
which takes a single boolean
parameter: ignoreVisible which as the name implies allows the calling code to create the control even if it is not visible. The CreateControl
method with no arguments passes false to this internal method which means that if the control is not visible, it is not created. So, the trick is to use Reflection to call the internal method. First, I created two methods for creating controls:
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 } );
}
Now, we add a call to CreateControls
for the second tab:
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 );
}
In addition, I added some debugging messages so I could see if the event fired:
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" );
}
}
Now, whether you navigate to the second tab or not, clicking on the button on the first tab will fire the checkbox1_Changed
event procedure. Given the design you provided, if you click on the button, it will not show the MessageBox because updating
will be true. However, the Debug.WriteLine
will show that it fired in the Output window.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…