.NET: Dock プロパティの優先順序を変更する方法

.NET FrameworkWindows Forms でコントロールを配置している時、Dock プロパティが思ったとおりに働かないことがある。例えば、エクスプローラ風のデザインで、ListView の下端が、後から追加した StatusBar の後ろに隠れてしまい、最後の行や横スクロールバーが表示されなくなったりする。

原因

以下の記事によれば、Dock プロパティによる位置計算順序は、コントロールが持つ「優先順位」にしたがって決まる。そして、その「優先順位」は、コントロールをフォームに追加した順であると同時に、表示する時の ZIndex にもなっている。

@IT会議室 - フォームの継承設計で接合PanelのDockプロパティの関係を変更したい
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=22105&forum=7&3

つまり、「Controls.Add した順に描画しますよ」というルールだ。
上記の例で言えば、配置した順番に従って ListView の位置が先に決められ (ウィンドウいっぱいにひろがり)、その後に StatusBar の位置が決められる (ウィンドウ下部に置かれる) ために、ListView の下側が隠れてしまっていることになる。

対処方法

これから作る場合
配置する順序が影響しているわけだから、配置するときに順序に気をつければ、悩まずにすむ。StatusBar を配置した後に ListView を配置すればいい。
もう配置しちゃった。配置するコードは GUI デザイナが管理しているから、触りたくない
GUI デザイナ上で ZIndex を変えることでうまくいくかも。SharpDevelop の場合でいうと、ListView を選択し、メニューの [Format]→[Order]→[Bring To Front] を選ぶ。最前面に移動するということは、最後に描画するわけなので、Dock プロパティによる位置計算も、他のコンポーネントより後に行われる。
プログラムから変えたい場合
さきほどの記事によれば、Control クラスの BringToFront メソッドか、ControlCollection クラスの SetChildIndex メソッドを呼び出すことでも変更できるようだ。

関連

優先順位の話は、Dock プロパティだけでなく ZIndex にも影響するので、上の対処方法が役に立つことは、他にもありそうだ。
例えば、Dock を Top にしたツールバーと Bottom にしたステータスバーがあるとする。ウィンドウの高さをちぢめていくと、両者がかぶってしまうが、ここでどちらが前面に表示されるか、というのにも、配置した順序が関係することになる。