2013年6月6日木曜日

TabControlのバグ?

突然ですが、適当なフォームにボタンおいてこんなコードを実行してみます。
private void button1_Click(object sender, EventArgs e){
    TabControl tab = new TabControl();
    TabPage page = new TabPage();
    tab.TabPages.Insert(0, page);
    page.Text = "test";
}

嘘みたいだろ…落ちるんだぜこれで
TabControlのコントロールハンドラが作成されていない状態でTabPageをインサートすると、
TabPageのParentはTabControlになっているのに、
TabControlのTabPagesには追加したTabPageが入っていないという状態になります。

で、この状態でTabPageのTextやImageIndexを設定すると、
TabControl内部の処理で「TabPageが自身の何番目にあるか」を探そうとするんですが、
TabControlにはTabPageが追加されてない状態になってるんでインデックスが-1になって、
これで内部でInvalidArgumentExceptionが発生する、って動きしてます。

こんな簡単なコードで.NET Framework内部でエラーが出せるってどうだろうと思いますが…

ちなみにInsertはダメだけどAddなら大丈夫のようです。
このため、Addを活用することでInsertまがいのことを行うことができます。

とりあえず、Extensionで実装してみました。

public static class TabPageCollectionExtension
{
    public static void FixedInsert(this TabControl.TabPageCollection tabPages, int index, TabPage page)
    {
        List<TabPage> tempList = new List<TabPage>();
        for (int i = 0; i < tabPages.Count; i++)
        {
            tempList.Add(tabPages[i]);
        }
        tabPages.Clear();
        tempList.Insert(index, page);
        for (int i = 0; i < tempList.Count; i++)
        {
            tabPages.Add(tempList[i]);
        }
    }
}

使い方はこんな感じ。

private void button2_Click(object sender, EventArgs e)
{
    TabControl tab = new TabControl();
    TabPage page1 = new TabPage("page1");
    TabPage page2 = new TabPage("page2");
    TabPage page3 = new TabPage("page3");
    tab.TabPages.Add(page1);
    tab.TabPages.FixedInsert(1, page2);
    tab.TabPages.FixedInsert(0, page3);
    this.Controls.Add(tab);
}

こんなシュールなことをやらされるとは思いませんでした…
コントロールハンドラの恐ろしさを知った一日でした。

(追記)
気になって調べてみたら、MSDNフォーラムで語られていました。
IntPtr h = this.tabControl1.Handle;
要は、これを足せと。知らなきゃわからんだろこれ…

0 件のコメント:

コメントを投稿