komoto / エンジニアブログ

プログラミングについてアウトプットします。

【.NET】ボタンクリックで入力フォーム部品を規則的に増やす

環境

はじめに

特定のボタンをクリックすると、入力フォームの部品を規則的に増やす方法について説明します。
ここでは下図のようなフォームで「プログラムの追加」ボタンをクリックすると、ラベル・テキストボックス・参照ボタンの一式を規則的に下に増やしたいという想定で話を進めます。

f:id:tkmt-hrkz:20200809135103p:plain

Form.cs[Design]の設定

まずはフォームのデザイン側の設定をしていきます。
デザイン側での設定は

  • 増加させる部品の親要素(コンテナやフォームウィンドウ)のスクロール設定
  • 要素(コンポーネント)の名前付け

の2点を行います。
部品を増やしていくと親要素の表示範囲を超えていくことが予想されますので、親要素にはスクロールできるように設定します。
私の場合、Panelというコンテナの中にこの一式を配置しているので、このPanelをスクロールできるようにします。
下のように親要素(コンポーネント)のプロパティの設定を変更して下さい。

コンポーネント プロパティ
増加させたい部品の親要素(コンテナまたはフォームウィンドウ) AutoScroll True

Nameは自分が分かりやすい識別子をつけてください。
ここでは下のようにNameを設定しています。

コンポーネント Name
1 「プログラムを追加」ボタン addProgButton
2 「プログラム名」ラベル prognameLabel1
3 「パス」ラベル pathLabel1
4 「プログラム名」テキストボックス prognameTextBox1
5 「パス」テキストボックス pathTextBox1
6 「参照」ボタン progRefeButton1
7 親要素のパネル allprogPanel

f:id:tkmt-hrkz:20200809142816p:plain

Form.csのコーディング

Form.csのコードは次のようになります。
上のName表と対応しているので合わせて見てください。

クリックイベントの処理の流れは以下の通りです。
クリック回数のカウント

部品一式の情報を設定(Name属性、表示するテキスト、表示位置、既存コンポーネントと新規コンポーネントの距離)

設定した情報からコンポーネントを生成する

//「プログラムを追加」ボタンのクリックイベント
private void addProgButton_Click(object sender, EventArgs e)
  {
    numberofAPBClicks++; //クリック回数のカウント、同クラスのメンバ変数

    //prognameLabel
    string PNLABEL_NAME = $"prognameLabel{numberofAPBClicks+1}";
    string PNLABEL_TEXT = $"{numberofAPBClicks+1}. プログラム名";
    //既存ラベルと新規ラベルの距離
    const int PNLABEL_OFFSET = 100; 
    int[] PNLABEL_LOCATE = {
      prognameLabel1.Location.X, //X座標
      PNLABEL_OFFSET * numberofAPBClicks + allProgPanel.AutoScrollPosition.Y //Y座標
    };

    //pathLabel
    string PATHLABEL_NAME = $"pathLabel{numberofAPBClicks+1}";
    const string PATHLABEL_TEXT = "パス";
    const int PATHLABEL_OFFSET = 100;
    int[] PATHLABEL_LOCATE = {
      pathLabel1.Location.X, //X座標
      PATHLABEL_OFFSET * numberofAPBClicks + allProgPanel.AutoScrollPosition.Y //Y座標
    };

    //prognameTextBox
    string PNBOX_NAME = $"prognameTextBox{numberofAPBClicks+1}";
    const int PNBOX_OFFSET = 100; //テキストボックス間の距離(Y)
    const int PNBOX_FIRST_OFFSET = 28; //Panelと最上部のテキストボックスとの距離(Y)
    int[] PNBOX_LOCATE = { 
      prognameTextBox1.Location.X, //X座標
      PNBOX_OFFSET * numberofAPBClicks + PNBOX_FIRST_OFFSET + allProgPanel.AutoScrollPosition.Y //Y座標
    };
    int[] PNBOX_SIZE = {
      prognameTextBox1.Size.Width, //テキストボックス幅
      prognameTextBox1.Size.Height //テキストボックス高さ
    };

    //pathTextBox
    string PATHBOX_NAME = $"pathTextBox{numberofAPBClicks+1}";
    const int PATHBOX_OFFSET = 100;
    const int PATHBOX_FIRST_OFFSET = 28; //Panelと最上部のテキストボックスとの距離(Y)
    int[] PATHBOX_LOCATE = {
      pathTextBox1.Location.X, //X座標
      PATHBOX_OFFSET * numberofAPBClicks + PATHBOX_FIRST_OFFSET + allProgPanel.AutoScrollPosition.Y //Y座標
    };
    int[] PATHBOX_SIZE = {
      pathTextBox1.Size.Width, //テキストボックス幅
      pathTextBox1.Size.Height //テキストボックス高さ
    };

    //progRefeButton
    string PRBUTTON_NAME = $"progRefeButton{numberofAPBClicks+1}";
    const string PRBUTTON_TEXT = "参照";
    int PRBUTTON_TAG = numberofAPBClicks + 1;
    const int PRBUTTON_OFFSET = 100;
    const int PRBUTTON_FIRST_OFFSET = 28; 
    int[] PRBUTTON_LOCATE ={
      progRefeButton1.Location.X,
      PRBUTTON_OFFSET * numberofAPBClicks + PRBUTTON_FIRST_OFFSET + allProgPanel.AutoScrollPosition.Y
    };
    int[] PRBUTTON_SIZE ={
    progRefeButton1.Size.Width,
    progRefeButton1.Size.Height
    };

  createLabel(PNLABEL_NAME, PNLABEL_TEXT, PNLABEL_LOCATE);
  createLabel(PATHLABEL_NAME, PATHLABEL_TEXT, PATHLABEL_LOCATE);
  createTextBox(PNBOX_NAME, PNBOX_LOCATE, PNBOX_SIZE);
  createTextBox(PATHBOX_NAME, PATHBOX_LOCATE, PATHBOX_SIZE);
  createButton(PRBUTTON_NAME, PRBUTTON_TEXT, PRBUTTON_TAG, PRBUTTON_LOCATE, PRBUTTON_SIZE);
}


//ラベルを生成するメソッド
//引数にはName属性、表示されるテキスト、ラベルの表示位置を渡す
private void createLabel(string name, string text, int[] locate)
{
  //ラベルのインスタンス生成
  Label label = new Label();
  //プロパティ設定
  label.Name = name;
  label.Location = new Point(locate[0], locate[1]);
  label.Text = text;
  //ラベルをパネルの子要素として追加
  allProgPanel.Controls.Add(label);
}

//テキストボックスを生成するメソッド
//引数にはName属性、ボックスの表示位置、ボックスの大きさを渡す
private void createTextBox(string name, int[] locate, int[] size)
{
  TextBox textBox = new TextBox();
  textBox.Name = name;
  textBox.Location = new Point(locate[0], locate[1]);
  textBox.Size = new Size(size[0], size[1]);
  allProgPanel.Controls.Add(textBox);
  return textBox;
}

//ボタンを生成するメソッド
//引数にはName属性、ボタンに表示されるテキスト、ボタンの表示位置、ボタンの大きさを渡す
private void createButton(string name, string text, int[] locate, int[] size)
{
  Button button = new Button();
  button.Name = name;
  button.Text = text;
  button.Location = new Point(locate[0], locate[1]);
  button.Size = new Size(size[0], size[1]);
  button.Click += progRefeButton_Click;
  allProgPanel.Controls.Add(button);
}

補足

要素(コンポーネント)のName属性とは

要素のName属性について説明しておきます。
f:id:tkmt-hrkz:20200809201027p:plain:w300

Name属性を指定することでコーディングをする際に、その指定したName値で要素のプロパティにアクセスしたり、各種イベント(クリックイベントなど)を検知したりできます。
なおデフォルトでは、ラベルの場合はlabel1、テキストボックスの場合はtextBox1などと設定されています。

例えば、label1.text = "Hello World!";でプログラム上でラベルのテキストを変更できますし、label1.BackColor = Blackなどとすることでラベルの背景色を変更できます。
アクセスできるプロパティや呼び出すことができるメソッド、設定できるイベントなどの詳細はこちら(Labelの場合)を確認してください