今回はユーザーコントロールを作ってみます。
ユーザーコントロールを使う事でプログラムが機能ごとに分割しやすくなり、自分の資産として他のプログラムへの流用もしやすくなりますので、是非覚えてご活用下さい。
ユーザーコントロールとは、LabelやTextBox、DataGridVIewなどのコントロールをグループ化して、1つのコントロールとして扱えるようにしたものです。
作り方や使い方を含め、詳しくは こちら に解説していますので、レイアウトを作る前にご一読下さい。
ユーザーコントロールの仕様を整理しよう
ユーザーコントロールを作る前に、どのようなものを作るか整理しておきましょう。
まずレイアウトは以下のようになります。

CSV結合ツールやCSV分割ツールで登場したファイル選択部分ですね。
仕様としては以下の様になります。
- 参照ボタンを押すとダイアログが表示される
- ダイアログで選択した結果がTextBox部分に表示される
- TextBoxの内容を外部から取り出したり、設定したりできる
- プロパティで参照と保存のダイアログを使い分けできる
この仕様を満たすために、TextBoxの内容を取り出したり設定するためのプロパティとして、FileNameプロパティを用意しましょう。
また、参照(OpenFileDialog)と保存(SaveFileDialog)を指定するためのプロパティとして SaveModeプロパティを用意しましょう。
今回はこの2つのプロパティだけで事が足りるため、外部に公開するメソッドは作成しません。
レイアウトを作ろう
今回はファイルを選択するためのユーザーコントロールなので、TextBox と Button を配置します。
まず、空のユーザーコントロールを作成し、FileSelectUserControl(正確には拡張子を含めてFileSelectUserControl.cs) という名前に変更して下さい。
空のユーザーコントロールが出来上がったら、今度はTextBox と Button の2つのコントロールをツールボックスからドラッグ&ドロップし、ユーザーコントロールに張り付けてください。
張り付けが終わったら、TextBoxコントロールは uxFileName という名前に、Button コントロールは uxSelect という名前に変更します。
手順は下記動画をご覧ください。

レイアウトと名前の変更が終わったら、いくつかのプロパティを設定していきます。
ここで注意すべき点は Anchor プロパティです。
Anchorを設定しよう
Anchor については前回簡単に解説しましたが、更に詳しい情報については こちら の記事をご覧ください。
Windowフォームのサイズ変更と一緒にユーザーコントロールも伸び縮みさせたいのですが、TextBoxとButtonが同じ様に延び縮みするとレイアウトが崩れるので、TextBoxだけ伸び縮みさせ、Buttonは右端に吸着させたいと思います。
そこで、TextBox の Anchor には Top,Left,Right を、Buttonの Anchor には Top,RIght を設定しておきます。

イベントハンドラを追加しよう
レイアウトが出来たら、Button(uxSelect) をダブルクリックしてイベントハンドラを追加して下さい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace CharCodeChanger { public partial class FileSelectUserControl : UserControl { public FileSelectUserControl() { InitializeComponent(); } private void uxSelect_Click(object sender, EventArgs e) { } } } |
プロパティを作成しよう
ユーザーコントロールは外部(張り付け先のWindowフォーム)と何らかのやり取りが必要になります。
たとえば、ユーザーコントロール内で設定した値をWindowフォーム側で取り出したり、逆にWindowフォームから任意の値を設定できなければなりません。
また、必要に応じてユーザーコントロール内にメソッドを用意することもあります。
今回はフィアルを選択するという目的と、ファイル参照と保存のダイアログを使い分けるという仕様にしましたので、ダイアログで選択(又は入力)したファイル名を取得するための FileName プロパティと、ダイアログを使い分けるための SaveMode プロパティを用意します。
下記は実際にプロパティを追加した結果です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace CharCodeChanger { public partial class FileSelectUserControl : UserControl { //ダイアログを保存用として使うことを指定するためのプロパティ public bool SaveMode { get; set; } = false; //選択されたファイル名 public string FileName { get { return uxFileName.Text; } set { uxFileName.Text = value; } } public FileSelectUserControl() { InitializeComponent(); } private void uxSelect_Click(object sender, EventArgs e) { } } } |
それでは、プロパティの定義について簡単に解説しておきます。
public bool SaveMode { get; set; } = false
と書かれていますが、public は外部からのアクセスを許可する記述で、bool 型はプロパティの型であり、SaveMode はプロパティの名前です。
また、get と set は参照と設定の両方を許可するという意味になります。
最後に = false と記述していますが、これは初期値としてfalse を設定しておくという事です。
一言で言うと、「外部から参照(get)と設定(set)が可能な SaveMode という名前のプロパティを、bool 型で定義し、初期値は false を設定する」という事になります。
public bool SaveMode = false;
という風に書く事も可能なのですが、これはプロパティではなくフィールドと呼ばれます。
何が違うかと言うと、プロパティの場合
public bool SaveMode { get; }
と記述すると、参照は出来ますが設定は出来ません。
この様に、外部からのアクセスに対して参照のみとか設定のみという具合に限定することが出来ます。
また、 get の中に処理を記述することも可能になっています。
public string FileName { get { return uxFileName.Text; } set { uxFileName.Text = value; } }
という2個目のプロパティの get は、関数の様に return があって、uxFileName.Text の値を返すような記述になっています。
また、set については uxFileName.Text = value とう風に値を設定するような書き方になっています。
フィールドは単なる変数の定義であり、外部から単純に読み書きしかできませんが、プロパティは外部に対してアクセス制限を掛けたり、加工して返すことが出来るという違いがあります。
イベントの中身を記述しよう
では、イベントの中身を記述していきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
private void uxSelect_Click(object sender, EventArgs e) { //選択か保存かによってダイアログを分ける if(SaveMode) { //ファイル保存ダイアログの表示 SaveFileDialog dialog = new SaveFileDialog() { FileName = uxFileName.Text }; //OKボタンがクリックされたら、ダイアログで選択したファイル名を取り出し、uxFileNameテキストボックスに表示 uxFileName.Text = (dialog.ShowDialog() == DialogResult.OK) ? dialog.FileName : uxFileName.Text; } else { //ファイル選択ダイアログの表示 OpenFileDialog dialog = new OpenFileDialog() { FileName = uxFileName.Text }; //OKボタンがクリックされたら、ダイアログで選択したファイル名を取り出し、uxFileNameテキストボックスに表示 uxFileName.Text = (dialog.ShowDialog() == DialogResult.OK) ? dialog.FileName : uxFileName.Text; } } |
SaveModeの値が true ならファイル保存用のSaveFileDialog を、 false なら ファイル参照用のOpenFileDialog を表示しています。
そして、ダイアログでOKボタンがクリックされた場合、ダイアログで選択した(或いは入力された)ファイル名を uxFileName.Text に設定しています。
つまり、SaveModeが true か false によってダイアログを使い分けているだけで、後の処理は全く同じです。
ユーザーコントロール全体のソース
では、ここまでの内容を盛り込んだ全体のソースを下記に掲載しておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace CharCodeChanger { public partial class FileSelectUserControl : UserControl { //ダイアログを保存用として使うことを指定するためのプロパティ public bool SaveMode { get; set; } = false; //選択されたファイル名 public string FileName { get { return uxFileName.Text; } set { uxFileName.Text = value; } } /// <summary> /// コンストラクタ /// </summary> public FileSelectUserControl() { InitializeComponent(); } /// <summary> /// 選択ボタンクリック処理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void uxSelect_Click(object sender, EventArgs e) { //選択か保存かによってダイアログを分ける if(SaveMode) { //ファイル保存ダイアログの表示 SaveFileDialog dialog = new SaveFileDialog() { FileName = uxFileName.Text }; //OKボタンがクリックされたら、ダイアログで選択したファイル名を取り出し、uxFileNameテキストボックスに表示 uxFileName.Text = (dialog.ShowDialog() == DialogResult.OK) ? dialog.FileName : uxFileName.Text; } else { //ファイル選択ダイアログの表示 OpenFileDialog dialog = new OpenFileDialog() { FileName = uxFileName.Text }; //OKボタンがクリックされたら、ダイアログで選択したファイル名を取り出し、uxFileNameテキストボックスに表示 uxFileName.Text = (dialog.ShowDialog() == DialogResult.OK) ? dialog.FileName : uxFileName.Text; } } } } |
まとめ
以上でユーザーコントロールの作成は完了です。
今回はファイル選択という役割のユーザーコントロールを作成してみました。
また、張り付けたコントロールのレイアウトを自動調整してくれる Anchor についても紹介いたしました。
次回は、このコントロールをMainFormに張り付けて CharCodeChanger のレイアウトを完成させたいと思います。