Ответ 1
Я думаю, что у меня есть решение. Проблема заключается не в том, что вы не можете создать Handle. Вы можете сделать это, просто обратившись к Access Access на Control. Проблема в том, что 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
покажет, что он запускается в окне вывода.