Принуждение флажка, обязанного с DataSource обновить, когда это еще не было просмотрено

Вот среда тестирования для показа то, что я делаю:

  1. создайте новый проект
  2. добавьте управление с вкладками
  3. на вкладке 1 помещает кнопку
  4. на вкладке 2 помещает флажок
  5. вставьте этот код для его кода

(используйте имена по умолчанию для средств управления),

public partial class Form1 : Form
{
    private List boolList = new List();
    BindingSource bs = new BindingSource();
    public Form1()
    {
        InitializeComponent();
        boolList.Add(false);
        bs.DataSource = boolList;
        checkBox1.DataBindings.Add("Checked", bs, "");
        this.button1.Click += new System.EventHandler(this.button1_Click);
        this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged);

    }
    bool updating = false;
    private void button1_Click(object sender, EventArgs e)
    {
        updating = true;
        boolList[0] = true;
        bs.ResetBindings(false);
        Application.DoEvents();
        updating = false;
    }

    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
        if (!updating)
            MessageBox.Show("CheckChanged fired outside of updating");
    }
}

Проблема - то, если Вы запускаете программу и смотрите на вкладку 2, затем нажимают кнопку на вкладке 1 работы программы как ожидалось, однако если Вы нажимаете, кнопка на вкладке 1 затем смотрят на вкладку 2, которую не запустит событие для флажка, непока Вы не посмотрите на вкладку 2.

Причиной этого является управление на вкладке 2, не находится в "созданном" состоянии, таким образом, его привязки для изменения флажка от непроверенного до проверенного не происходит, пока управление не было "Создано".

checkbox1. CreateControl () ничего не делает потому что согласно MSDN

CreateControl не создает дескриптор управления, если Свойство видимости управления является ложью. Можно или назвать метод CreateHandle или получить доступ к свойству Handle для создания дескриптора управления независимо от видимости управления, но в этом случае, никакие дескрипторы окна не создаются для детей управления.

Я пытался получить значение Дескриптора (нет никакого общедоступного CreateHandle () для CheckBox), но тем не менее тот же результат.

Какие-либо предложения кроме имеют программу, быстро высвечивают все мои вкладки, которые имеют флажки с привязкой к данным, когда она сначала загружается?

РЕДАКТИРОВАНИЕ - на предложение Jaxidian я создал новый класс

public class newcheckbox : CheckBox
{
    public new void CreateHandle()
    {
        base.CreateHandle();
    }
}

Я называю CreateHandle () прямо после updating = true те же результаты как прежде.

12
задан Scott Chamberlain 26 March 2010 в 18:04
поделиться

1 ответ

Думаю, у меня есть решение. Проблема не в том, что вы не можете создать дескриптор. Вы можете сделать это, просто обратившись к методу доступа Handle get в Control. Проблема в том, что WinForms не создает элемент управления, потому что он не виден. Как оказалось, за кулисами System.Windows.Forms.Control имеет две перегрузки для CreateControl . Первый, который является общедоступным, не принимает параметров и вызывает второй, который является внутренним , который принимает единственный логический параметр: 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 );
}

Кроме того, я добавил несколько отладочных сообщений, чтобы я мог видеть, если событие 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" );
    }
}

Теперь, независимо от того, перейдете ли вы на вторую вкладку или нет, нажатие кнопки на первой вкладке вызовет процедуру события checkbox1_Changed . С учетом предоставленного вами дизайна, если вы нажмете на кнопку, MessageBox не будет отображаться, потому что обновление будет истинным. Однако Debug.WriteLine покажет, что он активирован в окне вывода.

12
ответ дан 2 December 2019 в 21:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: