コンボボックスの表示名と実際の値を分けたい場合、次の2パターンの方法がポピュラーです。
- Items.Addで作成
- DataSourceで作成
画面仕様はとても簡単です。
- 左のコンボボックス…選択可能
- 右のテキストボックス…コンボボックスで選択されたアイテムの実際の値を表示
コンボボックスが選択されるとこうなります。
#Items.Addで作成する場合
まずは、Items.Addで作成する方法。
【必要なモノ】
- フォームとコンボボックス(当たり前)
- コンボボックス用の独自クラス
フォームとコンボボックスは先ほどの画像の通り。
コンボボックス用の独自クラスは次の様に作成します。
'【VB.NET】
'コンボボックス用の独自クラス
Public Class MyItems
'クラス変数
Private m_Code As String = ""
Private m_Name As String = ""
'コンストラクタ
Public Sub New(ByVal strCode As String, ByVal strName As String)
m_Code = strCode
m_Name = strName
End Sub
'プロパティ(実際の値)
Public ReadOnly Property Code() As String
Get
Return m_Code
End Get
End Property
'プロパティ(表示する名称)
Public ReadOnly Property Name() As String
Get
Return m_Name
End Get
End Property
'コンボボックス表示用メソッド(ToStringのオーバーライド)
Public Overrides Function ToString() As String
Return m_Name
End Function
End Class
//【C#】
//コンボボックス用の独自クラス
class MyItems
{
private string m_Code = "";
private string m_Name = "";
//コンストラクタ
public MyItems(string strCode, string strName)
{
m_Code = strCode;
m_Name = strName;
}
//プロパティ(実際の値)
public string Code
{
get
{
return m_Code;
}
}
//プロパティ(表示する名称)
public string Name
{
get
{
return m_Name;
}
}
//コンボボックス表示用メソッド(ToStringのオーバーライド)
public override string ToString()
{
return m_Name;
}
}
クラスを用意したら、次はフォーム画面のコード作成。
'【VB.NET】
'画面
Public Class Form_ComboBox
Private Sub Form_ComboBox_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim objItem As MyItems
'要素を独自クラスにセット①
objItem = New MyItems("01", "北海道")
'コンボボックスにセット②
cmbTest.Items.Add(objItem)
'要素を独自クラスにセット②
objItem = New MyItems("02", "青森県")
'コンボボックスにセット②
cmbTest.Items.Add(objItem)
'要素を独自クラスにセット②
objItem = New MyItems("03", "岩手県")
'コンボボックスにセット②
cmbTest.Items.Add(objItem)
End Sub
'SelectedIndexChangedイベント
Private Sub cmbTest_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbTest.SelectedIndexChanged
If cmbTest.SelectedIndex <> -1 Then
Dim objItem As MyItems
objItem = DirectCast(cmbTest.SelectedItem, MyItems)
'選択中のコード値をテキストボックスに表示
txtCode.Text = objItem.Code
End If
End Sub
End Class
//【C#】
//画面
public partial class Form_ComboBox : Form
{
public Form_ComboBox()
{
InitializeComponent();
}
private void Form_ComboBox_Load(object sender, EventArgs e)
{
MyItems objItem;
//要素を独自クラスにセット①
objItem = new MyItems("01", "北海道");
//コンボボックスにセット①
cmbTest.Items.Add(objItem);
//要素を独自クラスにセット②
objItem = new MyItems("02", "青森県");
//コンボボックスにセット②
cmbTest.Items.Add(objItem);
//要素を独自クラスにセット③
objItem = new MyItems("03", "岩手県");
//コンボボックスにセット③
cmbTest.Items.Add(objItem);
}
//SelectedIndexChangedイベント
private void cmbTest_SelectedIndexChanged(object sender, EventArgs e)
{
if (cmbTest.SelectedIndex != -1)
{
MyItems item;
//選択中のアイテムのオブジェクトを取得
item = (MyItems)cmbTest.SelectedItem;
//Idプロパティをラベルに表示
txtCode.Text = item.Code;
}
}
}
察しの良い方は既に分かると思いますが、コンボボックスに要素を1つずつ追加しています。
こんなこと、実際の現場ではなかなか見ません。
実際はSQLの結果や外部ファイルの値をコンボボックスに設定します。
なので、今回はCSVをインポートしてループ処理でコンボボックスの表示名と値を設定します。
'【VB.NET】
Imports System.Text 'CSVインポートで利用
Public Class Form_ComboBox
Private Sub Form_ComboBox_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'CSVファイル
Dim strFilePath As String = "D:\temp\Combo\todohuken.csv"
'CSVインポート
Using objIoTFP As New Microsoft.VisualBasic.FileIO.TextFieldParser(strFilePath, Encoding.GetEncoding("Shift_JIS"))
'読み込み時の設定
With objIoTFP
'区切り文字をカンマに設定
.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
.SetDelimiters(",")
'空白があった場合にTrimしない
.TrimWhiteSpace = False
End With
'コンボボックス用クラス
Dim objItem As MyItems
'CSV読み込み実行
While Not objIoTFP.EndOfData
'CSVの1行を配列にセット
Dim arrayRow As String() = objIoTFP.ReadFields()
'要素を独自クラスにセット
objItem = New MyItems(arrayRow(0), arrayRow(1))
'コンボボックスにセット
cmbTest.Items.Add(objItem)
End While
End Using
End Sub
'SelectedIndexChangedイベント
Private Sub cmbTest_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbTest.SelectedIndexChanged
If cmbTest.SelectedIndex <> -1 Then
Dim objItem As MyItems
objItem = DirectCast(cmbTest.SelectedItem, MyItems)
'選択中のコード値をテキストボックスに表示
txtCode.Text = objItem.Code
End If
End Sub
End Class
//【C#】
using Microsoft.VisualBasic.FileIO; //CSVインポートで利用
public partial class Form_ComboBox : Form
{
public Form_ComboBox()
{
InitializeComponent();
}
private void Form_ComboBox_Load(object sender, EventArgs e)
{
string strFilePath = "D:/temp/Combo/todohuken.csv";
//TextFieldParserのインスタンス生成
var objParser = new TextFieldParser(strFilePath, Encoding.GetEncoding("Shift_JIS"));
using (objParser)
{
//読み込み時の設定
//区切り文字をカンマ指定
objParser.TextFieldType = FieldType.Delimited;
objParser.SetDelimiters(",");
//空白があった場合にTrimしない
objParser.TrimWhiteSpace = false;
//コンボボックス用クラス
MyItems objItem;
//CSV読み込み実行
while (!objParser.EndOfData)
{
// CSVの1行を配列にセット
string[] arrayRow = objParser.ReadFields();
// 要素を独自クラスにセット
objItem = new MyItems(arrayRow[0], arrayRow[1]);
//コンボボックスにセット
cmbTest.Items.Add(objItem);
}
}
}
private void cmbTest_SelectedIndexChanged(object sender, EventArgs e)
{
if (cmbTest.SelectedIndex != -1)
{
MyItems item;
//Load時に追加したオブジェクトの中から選択中のものを取得
item = (MyItems)cmbTest.SelectedItem;
//Idプロパティをラベルに表示
txtCode.Text = item.Code;
}
}
}
#DataSourceで作成する場合
次にDataSourceで作成する方法。
【必要なモノ】
- フォームとコンボボックス(当たり前)
フォームとコンボボックスは先ほどの画像の通り。
以下の順序でコンボボックスのDataSourceに表示名と実際の値を格納します。
- フォームロード時にCSVをインポート
- CSVデータを配列に格納(実際の値、表示名)し、その配列をリストに格納
- リストを走査してDataTableを作成
- DataTableをコンボボックスのDataSourceにセット
尚、CSVインポート時にJet Providerで一気にDataTableを作成できますが、「配列からDataTableを作ってDataSourceにセットする」というステップを踏みたいので、敢えてTextFieldParserでのCSVインポートを実施しています。
※各現場で環境や制約が異なると思いますが、配列からDataTableが作成できないという現場は流石に無いと思いますので。
'【VB.NET】
Imports System.Text 'CSVインポートで利用
Public Class Form_ComboBox_DataTable
Private Sub Form_ComboBox_DataTable_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'CSVファイル
Dim strFilePath As String = "D:\temp\Combo\todohuken.csv"
'配列格納用リスト
Dim strListDT As List(Of String()) = New List(Of String())
'データテーブルの用意
Dim objDT As New DataTable()
objDT.Columns.Add("Code", GetType(String)) '実際の値
objDT.Columns.Add("Name", GetType(String)) '表示名
'CSVインポート
Using objIoTFP As New Microsoft.VisualBasic.FileIO.TextFieldParser(strFilePath, Encoding.GetEncoding("Shift_JIS"))
'読み込み時の設定
With objIoTFP
'区切り文字をカンマに設定
.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
.SetDelimiters(",")
'空白があった場合にTrimしない
.TrimWhiteSpace = False
End With
'CSV読み込み実行
While Not objIoTFP.EndOfData
'CSVの1行を配列にセット
Dim arrayRow As String() = objIoTFP.ReadFields()
'配列格納用リストにセット
strListDT.Add(arrayRow)
End While
End Using
'データテーブルの作成
For Each strArray As String() In strListDT
'データテーブル用の行オブジェクトを作成
Dim objDR As DataRow = objDT.NewRow()
objDR("Code") = strArray(0) '実際の値(ValueMember)
objDR("Name") = strArray(1) '表示名(DisplayMember)
'配列格納用リストに行オブジェクトを格納
objDT.Rows.Add(objDR)
Next
'データテーブルのコミット
objDT.AcceptChanges()
'データテーブルをコンボボックスのデータソースにセット
cmbTest.DataSource = objDT
'ValueMemberとDisplayMemberを設定
cmbTest.ValueMember = "Code" '実際の値
cmbTest.DisplayMember = "Name" '表示名
End Sub
'SelectedIndexChangedイベント()
Private Sub cmbTest_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbTest.SelectedIndexChanged
If cmbTest.SelectedIndex <> -1 Then
'選択中のコード値をテキストボックスに表示
txtCode.Text = cmbTest.SelectedValue.ToString()
End If
End Sub
End Class
//【C#】
using Microsoft.VisualBasic.FileIO; //CSVインポートで利用
namespace CS_ComboBox_DataTable
{
public partial class Form_ComboBox_DataTable : Form
{
public Form_ComboBox_DataTable()
{
InitializeComponent();
}
private void Form_ComboBox_DataTable_Load(object sender, EventArgs e)
{
//CSVファイル
string strFilePath = "D:/temp/Combo/todohuken.csv";
//配列格納用リスト
List<String[]> strListDT = new List<String[]>();
//データテーブルの用意
DataTable objDT = new DataTable();
objDT.Columns.Add("Code", typeof(String)); //実際の値
objDT.Columns.Add("Name", typeof(String)); //表示名
//TextFieldParserのインスタンス生成
var objParser = new TextFieldParser(strFilePath, Encoding.GetEncoding("Shift_JIS"));
using (objParser)
{
// 読み込み時の設定
// 区切り文字をカンマ指定
objParser.TextFieldType = FieldType.Delimited;
objParser.SetDelimiters(",");
// 空白があった場合にTrimしない
objParser.TrimWhiteSpace = false;
// CSV読み込み実行
while (!objParser.EndOfData)
{
// CSVの1行を配列にセット
string[] arrayRow = objParser.ReadFields();
//リストにセット
strListDT.Add(arrayRow);
}
}
//データテーブルの作成
foreach(string[] strArray in strListDT)
{
//データテーブル用の行オブジェクトを作成
DataRow objDR = objDT.NewRow();
objDR["Code"] = strArray[0]; //実際の値(ValueMember)
objDR["Name"] = strArray[1]; //表示名(DisplayMember)
//配列格納用リストに行オブジェクトを格納
objDT.Rows.Add(objDR);
}
//データテーブルのコミット
objDT.AcceptChanges();
//データテーブルをコンボボックスのデータソースにセット
cmbTest.DataSource = objDT;
//ValueMemberとDisplayMemberを設定
cmbTest.ValueMember = "Code";
cmbTest.DisplayMember = "Name";
}
private void cmbTest_SelectedIndexChanged(object sender, EventArgs e)
{
//選択されていればSelectedValueに入っている
if (cmbTest.SelectedIndex != -1)
{
//選択中のコード値をテキストボックスに表示
txtCode.Text = cmbTest.SelectedValue.ToString();
}
}
}
}
CSVの部分をSQLに書き換えても使えます。
データテーブルの作成の処理の前に、リストの中に配列が入っていればOKです。
データテーブルの作成に至る前に、リストの中に配列を入れています。二次元配列か多段階配列にする方法も考えましたが、ソースコードが非常に煩雑になるため、リストにしています。
#参考