プロが教える店舗&オフィスのセキュリティ対策術

図のように"追加ボタン"を押すと親パネル(panel1)に子パネル(panel2)を上から
追加する画面を作りました。(以下がソースです)

private void button1_Click(object sender, EventArgs e)
{

int i = 0;

foreach (Panel p in panel1.Controls)
{
i++;
p.Top += 40;
}

Panel panel2 = new Panel();
createPanel(panel2, i);※子パネルのレイアウトを設定し、確認用の連番をセットしています

panel1.Controls.Add(panel2);

}

常に親パネルの最上段に子パネルを追加したいのですが、
スクロールバーで親パネルの下のほうで追加ボタンを押すと、
親パネルの表示されている最上段の位置に子パネルが追加されてしまいます。

スクロールバーで親パネルの最下部に移動していても、追加するときは親パネルの(0,0,)の位置に
子パネルを表示させるにはどのように実装したらよいでしょうか?

メソッドcreatePanel(panel2, i)の中で、
子パネルのロケーションを0,0に設定してもダメでした。

以上、よろしくお願いいたします。

「C#でパネルに子パネルを上から降順追加し」の質問画像

A 回答 (1件)

まず,親パネルのかわりにFlowLayoutPanellを使って下さい。


この時,
・FlowDirectionをTopDownにする
→内部のコントロールを上端から下に並べる
※BottomUpは下端から上に並べていく
・WrapContentsをFalseにする
→コントロールが入りきらない場合にコントロールを折り返して配置させない
・AutoScrollをTrueにする
→コントロールが入りきらない場合にスクロールバーを表示する
という設定が必要になります。

次に,基本的にはコントロールをControls.Addで追加していくのですが,
上記のプロパティからわかるように,単純に追加すると一番下に追加されます。
これを避けるために,Controls.AddのあとにControls.SetChildIndexでnewIndexに0を指定し,
追加したコントロールを一番上になるようにします。

最後に,幅の調整です。
Dock系による調整が出来ないので,丁度の幅にするには
FlowLayoutPanelのClientSize.Widthから追加したコントロールのMargine.Horizontalを引くことで出せますが,
これだけだとスクロールバーが表示されたタイミングで幅がずれます。
いくつか試したところ,
1. FlowLayoutPanelをSuspendLayoutする
2. FlowLayoutPanelのAutoScrollをfalseにする
3. FlowLayoutPanelの全ての子コントロールの幅を調整する
4. FlowLayoutPanelのAutoScrollをtrueにする
5. FlowLayoutPanelをResumeLayoutする
でできました。

以下,TextBoxを追加していくサンプル (C# on .NET Framework 4) です。
・FlowLayoutPanel型のコントロールflowLayoutPanel1
・Button型のコントロールbutton1
を置き,
・button1.Clickイベントにbutton1_Click
・flowLayoutPanel1.ResizeイベントにflowLayoutPanel1_Resize
を設定しています。
また,_をスペースに,もしくは____をタブに変換してください。

private void button1_Click (object sender, EventArgs e)
{
____var textBox = new TextBox() { Text = flowLayoutPanel1.Controls.Count.ToString() };
____flowLayoutPanel1.Controls.Add(textBox);
____flowLayoutPanel1.Controls.SetChildIndex(textBox, 0);
____ResetChildSize();
}

private void flowLayoutPanel1_Resize (object sender, EventArgs e)
{
____ResetChildSize();
}

private void ResetChildSize ()
{
____flowLayoutPanel1.SuspendLayout();
____flowLayoutPanel1.AutoScroll = false;
____foreach (var control in flowLayoutPanel1.Controls.Cast<Control>())
____{
________control.Width = flowLayoutPanel1.ClientSize.Width - control.Margin.Horizontal;
____}
____flowLayoutPanel1.AutoScroll = true;
____flowLayoutPanel1.ResumeLayout();
}


ところで,子パネルはユーザーコントロール化できないのですか。
Panelよりも色々と便利なことが多いですけれども……。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!