开发者

C# Why isn't it possible to set GUI specific actions in the winform constructor?

I was wondering why it isn't possible to set some properties in the constructor of a winform. For example, I have an Expandable splitter (devcomponents library) and when i set the property Expanded to false, in the constructor nothing happens, but when I put the same code in the form load event, it works like expected. I am putting this code after the InitializeComponent() method.

Another situation, slighty different though, is this. When you dynamically create a combobox in a class and you set the selected index other then the first item and then return this combobox, the selected index is set back to 1 on the form.

Why is this?

Code snippet on the first situation (updated):

// This works in the form_load event but not in the form constructor (after InitializeComponent())
if (_tabId != -1)
{
    this.SuspendLayout();
    expandableSplitter1.SuspendLayout();

    expandableSplitter1.Expanded = false;
    expandableSplitter1.Enabled = false;

    // Hide all开发者_开发问答 tabs, except the selected tab
    tabControl1.Tabs.Clear();

    QuestionTab tab = new QuestionTab(_tabId);

    TabItem tabItem = tabControl1.CreateTab(tab.Description);
    tabItem.Tag = tab;

    tabControl1.SelectedTabIndex = 0;

    TabItem_Click(tabItem, null);

    expandableSplitter1.ResumeLayout(true);
    this.ResumeLayout(true);
}

Code snippet for the second situation:

public Control GenerateList(Question question)
{
    // some code is omitted

    ComboBox cmb = new ComboBox();

    cmb.SuspendLayout();

    cmb.Name = "cmb";
    cmb.DisplayMember = "Answer";
    cmb.ValueMember = "Id";
    cmb.DataSource = answers;
    cmb.Dock = DockStyle.Top;

    cmb.SelectedValue = 3; // not the first index


    cmb.DropDownStyle = ComboBoxStyle.DropDownList;
    cmb.SelectedIndexChanged += new EventHandler(cmb_SelectedIndexChanged);

    cmb.ResumeLayout(true);

    return cmb;
}


The problem is, that these properties have an side effect. This will lead to an invalidation of the control, which tries to redraw itself but this doesn't work cause actually we're in the constructor and there is nothing we can paint on. Thus leading to a switch back to the previous or a default value (depending on the implementation of the concrete control).

To get this to work you should take a closer look into the InitializeComponent() function. Before it starts to set anything within the controls it calls a Control.SuspendLayout() and afterwards a Control.ResumeLayout(false).

You should do the same, but not only on the control itself, also on all parent controls (maybe a TableLayoutPanel or any other container control) till you reach the top by calling this.SuspendLayout().

Also you should take care of the order. Suspend from top control (this) down to your exact one you like and resume in the reverse order. In case of the standard windows controls this should work. If you use any 3rd party control than it's up to the vendor to take care of that.

Update

After reading your updates and comments i made a new project put a TabControl with some pages on it. Also i put a ComboBox on the third page and added some items to it.

Then i changed my code as follows:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        tabControl1.SelectedIndex = 1;
        comboBox1.SelectedIndex = 2;
    }
}

and it works as expected (without using SuspendLayout() or ResumeLayout()).

So to really find the bug in your application, start a new empty one and start filling it up with your existing code or just use the OnLoad() approach.


I'm guessing the one of the events of the ExpandableSplitter defaults it to true. DevComponents stuff is funny. Are you setting it before or after InitializeComponent() is called?

No idea on the second one.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜