トップ回答者
VB、コンボボックスへのサーバーデータ表示について、教えてください。

質問
-
使用のVBは、Vb 2010 Express,サーバーはSQL2003(SQL認証接続)---サーバーには問題ありません。 現在正常に使用中です。
作成中のフォームのコンボボックス(CB_Country_ID)には、現在数値が表示されています---サーバーデータを直接表示しました(作業を簡単にするため)。
サーバーのテーブルの該当項目(列:Country_ID)には、ID(数値---Country_ID)のみが保存されていて、名前等は別テーブルにあります。
別テーブル(T_M_Country)には、Country_ID(主キー)、CountryName、CountryCode等の詳細が格納されています。コンボボックス表示自体は、SQL認証接続しデータソースをテーブルT_M_Countryとし、 Me.CB_Country_ID.ValueMember = "CountryName"として
成功しています。フォームを開いたとき、このコンボボックスは、本来はCountryNameを表示しなければならないのですが、うまくいきません。
どのようにしたら良いか、教えてください(丸一日頑張ったのですが、だめでした)。よろしく、お願いします。
- 編集済み yksaila 2012年4月23日 4:15
回答
-
ただ、フォーム表示の際、サーバーデータの1行目だけがCountryShortNameにならず、 Country_IDになるのです。
例:Japan-- CountryShortName=’JPN’、Country_ID=’1’、CountryCode=’81’
USA-- CountryShortName=’USA’、Country_ID=’2’、CountryCode=’1’
ITALY-- CountryShortName=’ITA、Country_ID=’3’、CountryCode=’39’
この例で、JAPANだけは’1’が表示され、他はUSA,ITAと表示します。 JAPANだけコンボ表示が、CountryShortNameにならず、 Country_IDになるようです。
他は(USA,ITALY)はきちんと表示します(コンボボックスで)。
サーバーデータの表示順を変更しても同じです。 1行目というわけではなく、Country_IDの最初の数字に原因があるようです。
これは実装の問題だと思います。
>>1.表示するとき:
>> 'コンボボックスのデータ:From SERVERテーブル(T_M_Client)
>> Me.CB_Country_ID.Text = dt.Rows(n).Item("Country_ID") ----’サーバーからCountry_IDをひきだしてくる。
>> Me.CB_Country_ID.SelectedValue = Convert.ToString(Me.CB_Country_ID.Text) ----’コンボボックス表示名(CountryShortName)恐らくこれが原因ですね。
Me.CB_Country_ID.Text = dt.Rows(n).Item("Country_ID") ----’サーバーからCountry_IDをひきだしてくる。
Me.CB_Country_ID.SelectedValue = Convert.ToString(Me.CB_Country_ID.Text) ----’コンボボックス表示名(CountryShortName)
これを、
Me.CB_Country_ID.SelectedValue = dt.Rows(n).Item("Country_ID").ToString()
こうして下さい。- 回答としてマーク yksaila 2012年4月26日 5:18
-
aviator_さんへ
ありがとうございます。 ご教示のコードについても、再度実験してみます(大変、勉強になります)。
私も、あれからやってみたことを下記に記します。
0.コンボボックス設定時---フォームを開くとき(Load時と修正後表示の両方に設定必要)
'コンボボックス:CB_Country_ID ----コンボボックス表示準備
Dim dsCombo1 = New DataSet
Dim sqCombo1 As String
sqCombo1 = "SELECT T_M_Country.* FROM T_M_Country"
adapter.SelectCommand = New SqlClient.SqlCommand(sqCombo1, Con)
adapter.SelectCommand.CommandType = CommandType.Text
adapter.Fill(dsCombo1)
Dim dtCombo1 As New DataTable
dtCombo1 = dsCombo1.Tables(0)
'Me.DataGridView1.DataSource = dtCombo1---’使用せず
Me.CB_Country_ID.DataSource = dtCombo1Me.CB_Country_ID.DisplayMember = "CountryShortName"
Me.CB_Country_ID.ValueMember = "Country_ID"1.表示するとき:
'コンボボックスのデータ:From SERVERテーブル(T_M_Client)
Me.CB_Country_ID.Text = dt.Rows(n).Item("Country_ID") ----’サーバーからCountry_IDをひきだしてくる。
Me.CB_Country_ID.SelectedValue = Convert.ToString(Me.CB_Country_ID.Text) ----’コンボボックス表示名(CountryShortName)
’おまけ
Me.TX_CountryCode.Text = Me.CB_Country_ID.SelectedItem("CountryCode").ToString ---’関連データを表示(コンボボックスの隣のテキストボックスに)
2.修正・変更時:
sql.Parameters.AddWithValue("@Country_ID", Convert.ToInt32(Me.CB_Country_ID.SelectedValue))上記でうまくいきました。
ただ、フォーム表示の際、サーバーデータの1行目だけがCountryShortNameにならず、 Country_IDになるのです。
例:Japan-- CountryShortName=’JPN’、Country_ID=’1’、CountryCode=’81’
USA-- CountryShortName=’USA’、Country_ID=’2’、CountryCode=’1’
ITALY-- CountryShortName=’ITA、Country_ID=’3’、CountryCode=’39’
この例で、JAPANだけは’1’が表示され、他はUSA,ITAと表示します。 JAPANだけコンボ表示が、CountryShortNameにならず、 Country_IDになるようです。
他は(USA,ITALY)はきちんと表示します(コンボボックスで)。
サーバーデータの表示順を変更しても同じです。 1行目というわけではなく、Country_IDの最初の数字に原因があるようです。
ところが、別のコンボ(例:Staff_ID)では、Staff_IDの数字順ではなく、表示の最初の行のデータのみが、ID表示でそれ以降はName(Staff_Name)を表示します。
私の対策:サーバーデータに、ダミーデータを追加、ID=’0’、Nameは適当(??とか)。--- 良いやり方とは言えませんが。
これで、コンボにこれが表示されます(ダミー選択時は、NameでなくID=’0’表示)が、他のデータは完璧に表示します(JAPANもID表示’0’でなく、Nameの’JPN’が表示します)。
なぜか、現時点では不明です。 ほぼ1日やっていますが、どこかのバグなのか、私のコードがおかしいのか(おかしかったら、全部表示できないはずですよね)わかりません?
教えていただいた、コードでもやってみます。 うまくしたら、上記の問題が発生しないかもしれないですね。
この問題は最初の私のコードでは発生していません、でもこれはエレガントではないですし他の問題点にも気付いていますので、.ValueMember, .DisplayMeber を使うべきだと思います(正しく)。
yksaila
- 回答としてマーク yksaila 2012年4月26日 5:18
-
ただ、フォーム表示の際、サーバーデータの1行目だけがCountryShortNameにならず、 Country_IDになるのです。
例:Japan-- CountryShortName=’JPN’、Country_ID=’1’、CountryCode=’81’
USA-- CountryShortName=’USA’、Country_ID=’2’、CountryCode=’1’
ITALY-- CountryShortName=’ITA、Country_ID=’3’、CountryCode=’39’
この例で、JAPANだけは’1’が表示され、他はUSA,ITAと表示します。 JAPANだけコンボ表示が、CountryShortNameにならず、 Country_IDになるようです。
他は(USA,ITALY)はきちんと表示します(コンボボックスで)。
サーバーデータの表示順を変更しても同じです。 1行目というわけではなく、Country_IDの最初の数字に原因があるようです。
これは実装の問題だと思います。
>>1.表示するとき:
>> 'コンボボックスのデータ:From SERVERテーブル(T_M_Client)
>> Me.CB_Country_ID.Text = dt.Rows(n).Item("Country_ID") ----’サーバーからCountry_IDをひきだしてくる。
>> Me.CB_Country_ID.SelectedValue = Convert.ToString(Me.CB_Country_ID.Text) ----’コンボボックス表示名(CountryShortName)恐らくこれが原因ですね。
Me.CB_Country_ID.Text = dt.Rows(n).Item("Country_ID") ----’サーバーからCountry_IDをひきだしてくる。
Me.CB_Country_ID.SelectedValue = Convert.ToString(Me.CB_Country_ID.Text) ----’コンボボックス表示名(CountryShortName)
これを、
Me.CB_Country_ID.SelectedValue = dt.Rows(n).Item("Country_ID").ToString()
こうして下さい。aviator_さんへ
ありがとうございます。
Me.CB_Country_ID.SelectedValue = dt.Rows(n).Item("Country_ID").ToString() の、一行だけですね。 これで、成功しました。 完璧です。
これで、先へ進めます。 独力では無理でした、感謝しています。
ところで、この行の最後は、.Tostringは、あってもなくても動作します。 どちらが良いのでしょうか? サーバーから引き出したデータは、数値ですし、コンボ表示は文字型ですし?
yksaila
- 回答としてマーク yksaila 2012年4月27日 8:48
すべての返信
-
回答、ありがとうございました。
でも、うまくいかないのです。
下記のようにして、やっと先ほど解決しました。 これで、良いのではないでしょうか?
1.コンボボックス設定--- コンボボックスのクリック時に設定
SQL認証接続後(これは省略);'コンボボックス(CB_Country_ID)
Dim dsCombo1 = New DataSet
Dim sqCombo1 As String
sqCombo1 = "SELECT * FROM dbo.T_M_Country"
Dim adapter = New SqlClient.SqlDataAdapter()
adapter.SelectCommand = New SqlClient.SqlCommand(sqCombo1, Cn)
adapter.SelectCommand.CommandType = CommandType.Text
adapter.Fill(dsCombo1)Dim dtCombo1 As New DataTable
dtCombo1 = dsCombo1.Tables(0)
'Me.DataGridView1.DataSource = dtCombo1---’使用せず
Me.CB_Country_ID.DataSource = dtCombo1
Me.CB_Country_ID.ValueMember = "CountryShortName"Cn.Close()
'▼後処理,追加-2012/04/16
'dtCombo1.Dispose() ----’ここは、Dispose不可
adapter.Dispose()
SQL.Dispose()
Cn.Dispose()これで、コンボボックスは通常どおりに表示できました。
2.データ表示するとき(サーバーからのデータ受け取り時);フォームを開くとき
サーバーからは数値(Country_ID)のみ受け取っているので、
Dim X As Integer
X = NZint(Me.CB_Country_ID.Text)---念のためIntegerにしておく(不要だけど)コンボボックスのもとになっているテーブル(dtCombo1)から、CountryNameをひきだしてくる。
Me.CB_Country_ID.Text = dtCombo1.Rows(X - 1)("CountryName").ToStringこれで、コンボボックスにはID(数字)でなく、CountryNameが表示されました。
3.フォームでのデータ修正・変更時
'コンボボックス---コンボボックス表示データのINDEX取得
Dim x
x = Me.CB_Country_ID.SelectedIndex
x = x + 1'コンボボックス
○:sql.Parameters.AddWithValue("@Country_ID", x)
×:sql.Parameters.AddWithValue("@Country_ID", NZint(Me.CB_Country_ID.Text)) ---これは、以前のもので、上記(○印)に変更これで、全てうまくいきました。
yksaila
-
参考サイトの内容は見てみましたか?
DisplayMember と ValueMember の意味合いを理解されていない様に感じます。
今回のケースであれば、下記の様に指定すべきではないでしょうか。1.コンボボックス設定--- コンボボックスのクリック時に設定
・・・
Me.CB_Country_ID.DisplayMember = "CountryShortName"
Me.CB_Country_ID.ValueMember = "Country_ID"2.データ表示するとき(サーバーからのデータ受け取り時);フォームを開くとき
Me.CB_Country_ID.SelectedValue = Me.CB_Country_ID.Text3.フォームでのデータ修正・変更時
sql.Parameters.AddWithValue("@Country_ID", Convert.ToInt32(Me.CB_Country_ID.SelectedValue))私の思いすごしであればすいません。
- 編集済み aviator__ 2012年4月23日 7:38 3.の内容を追記
-
aviator_ さんへ
丁寧な、ご回答ありがとうございました。 やってみたのですが、下記のコメントがでるのす。
”ListControl の SelectedValue を空の ValueMember で設定できません。”
私も、なぜそうなるのか興味もありますし、自分の勉強にもなりますのでこの件はもう少し追求してみます。 この方法でできれば、最善ですので。
現在少し疲れていますので、どこか間違えているのかも知れません。 今日は長時間の勉強なので(朝8時から、です)、もう集中できないのです。
おって、ご返事いたします。 他の用事もありますので、数日後になるかもしれません。
yksaila
-
こちらでも確認したのですが、上記の内容であれば動作すると思われます。
ちなみに下記が検証内容です。Public Class Form1 Private Const ID_COLUMN As String = "Country_ID" Private Const NAME_COLUMN As String = "CountryShortName" Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim table As New DataTable() table.Columns.Add(New System.Data.DataColumn(ID_COLUMN, System.Type.GetType("System.Int32"))) table.Columns.Add(New System.Data.DataColumn(NAME_COLUMN, System.Type.GetType("System.String"))) For index As Integer = 1 To 10 Dim row As DataRow = table.NewRow() row(ID_COLUMN) = index row(NAME_COLUMN) = "項目" + index.ToString() table.Rows.Add(row) Next ComboBox1.DropDownStyle = ComboBoxStyle.DropDownList ComboBox1.DataSource = table ComboBox1.DisplayMember = NAME_COLUMN ComboBox1.ValueMember = ID_COLUMN ComboBox1.SelectedValue = 5 Text = ComboBox1.SelectedValue.ToString() End Sub End Class
上記のソースを実行した結果です。
-
-
合わせてメッセージ内容からの推測ですが、
Me.CB_Country_ID.ValueMember = "CountryShortName"
を、
Me.CB_Country_ID.DisplayMember = "CountryShortName"
Me.CB_Country_ID.ValueMember = "Country_ID"と変更すべき所で、
Me.CB_Country_ID.DisplayMember = "CountryShortName"
としてしまっていませんか?
※ValueMemberを指定し忘れていませんか?見直してみました、確かにこの掲示板には、 Me.CB_Country_ID.ValueMember = "CountryShortName"と書いていますね。
おっしゃる通りです、今はもうこの部分は書き換えて残っていないのではっきりしませんが、コピー・貼り付けでやっていますので、きっと私の間違いです。
その時は、私がDisplayMember ・ValueMember をしっかり理解していなかったんだと思います。
その後のコードについては、すぐにアップします。
-
aviator_さんへ
ありがとうございます。 ご教示のコードについても、再度実験してみます(大変、勉強になります)。
私も、あれからやってみたことを下記に記します。
0.コンボボックス設定時---フォームを開くとき(Load時と修正後表示の両方に設定必要)
'コンボボックス:CB_Country_ID ----コンボボックス表示準備
Dim dsCombo1 = New DataSet
Dim sqCombo1 As String
sqCombo1 = "SELECT T_M_Country.* FROM T_M_Country"
adapter.SelectCommand = New SqlClient.SqlCommand(sqCombo1, Con)
adapter.SelectCommand.CommandType = CommandType.Text
adapter.Fill(dsCombo1)
Dim dtCombo1 As New DataTable
dtCombo1 = dsCombo1.Tables(0)
'Me.DataGridView1.DataSource = dtCombo1---’使用せず
Me.CB_Country_ID.DataSource = dtCombo1Me.CB_Country_ID.DisplayMember = "CountryShortName"
Me.CB_Country_ID.ValueMember = "Country_ID"1.表示するとき:
'コンボボックスのデータ:From SERVERテーブル(T_M_Client)
Me.CB_Country_ID.Text = dt.Rows(n).Item("Country_ID") ----’サーバーからCountry_IDをひきだしてくる。
Me.CB_Country_ID.SelectedValue = Convert.ToString(Me.CB_Country_ID.Text) ----’コンボボックス表示名(CountryShortName)
’おまけ
Me.TX_CountryCode.Text = Me.CB_Country_ID.SelectedItem("CountryCode").ToString ---’関連データを表示(コンボボックスの隣のテキストボックスに)
2.修正・変更時:
sql.Parameters.AddWithValue("@Country_ID", Convert.ToInt32(Me.CB_Country_ID.SelectedValue))上記でうまくいきました。
ただ、フォーム表示の際、サーバーデータの1行目だけがCountryShortNameにならず、 Country_IDになるのです。
例:Japan-- CountryShortName=’JPN’、Country_ID=’1’、CountryCode=’81’
USA-- CountryShortName=’USA’、Country_ID=’2’、CountryCode=’1’
ITALY-- CountryShortName=’ITA、Country_ID=’3’、CountryCode=’39’
この例で、JAPANだけは’1’が表示され、他はUSA,ITAと表示します。 JAPANだけコンボ表示が、CountryShortNameにならず、 Country_IDになるようです。
他は(USA,ITALY)はきちんと表示します(コンボボックスで)。
サーバーデータの表示順を変更しても同じです。 1行目というわけではなく、Country_IDの最初の数字に原因があるようです。
ところが、別のコンボ(例:Staff_ID)では、Staff_IDの数字順ではなく、表示の最初の行のデータのみが、ID表示でそれ以降はName(Staff_Name)を表示します。
私の対策:サーバーデータに、ダミーデータを追加、ID=’0’、Nameは適当(??とか)。--- 良いやり方とは言えませんが。
これで、コンボにこれが表示されます(ダミー選択時は、NameでなくID=’0’表示)が、他のデータは完璧に表示します(JAPANもID表示’0’でなく、Nameの’JPN’が表示します)。
なぜか、現時点では不明です。 ほぼ1日やっていますが、どこかのバグなのか、私のコードがおかしいのか(おかしかったら、全部表示できないはずですよね)わかりません?
教えていただいた、コードでもやってみます。 うまくしたら、上記の問題が発生しないかもしれないですね。
この問題は最初の私のコードでは発生していません、でもこれはエレガントではないですし他の問題点にも気付いていますので、.ValueMember, .DisplayMeber を使うべきだと思います(正しく)。
yksaila
- 回答としてマーク yksaila 2012年4月26日 5:18
-
aviator_ さんへ
丁寧な、ご回答ありがとうございました。 やってみたのですが、下記のコメントがでるのす。
”ListControl の SelectedValue を空の ValueMember で設定できません。”
私も、なぜそうなるのか興味もありますし、自分の勉強にもなりますのでこの件はもう少し追求してみます。 この方法でできれば、最善ですので。
現在少し疲れていますので、どこか間違えているのかも知れません。 今日は長時間の勉強なので(朝8時から、です)、もう集中できないのです。
おって、ご返事いたします。 他の用事もありますので、数日後になるかもしれません。
yksaila
これは、サーバーデータの間違いでした(ダミーでデータ入力した時の、誤りでした)。
yksaila
-
ただ、フォーム表示の際、サーバーデータの1行目だけがCountryShortNameにならず、 Country_IDになるのです。
例:Japan-- CountryShortName=’JPN’、Country_ID=’1’、CountryCode=’81’
USA-- CountryShortName=’USA’、Country_ID=’2’、CountryCode=’1’
ITALY-- CountryShortName=’ITA、Country_ID=’3’、CountryCode=’39’
この例で、JAPANだけは’1’が表示され、他はUSA,ITAと表示します。 JAPANだけコンボ表示が、CountryShortNameにならず、 Country_IDになるようです。
他は(USA,ITALY)はきちんと表示します(コンボボックスで)。
サーバーデータの表示順を変更しても同じです。 1行目というわけではなく、Country_IDの最初の数字に原因があるようです。
これは実装の問題だと思います。
>>1.表示するとき:
>> 'コンボボックスのデータ:From SERVERテーブル(T_M_Client)
>> Me.CB_Country_ID.Text = dt.Rows(n).Item("Country_ID") ----’サーバーからCountry_IDをひきだしてくる。
>> Me.CB_Country_ID.SelectedValue = Convert.ToString(Me.CB_Country_ID.Text) ----’コンボボックス表示名(CountryShortName)恐らくこれが原因ですね。
Me.CB_Country_ID.Text = dt.Rows(n).Item("Country_ID") ----’サーバーからCountry_IDをひきだしてくる。
Me.CB_Country_ID.SelectedValue = Convert.ToString(Me.CB_Country_ID.Text) ----’コンボボックス表示名(CountryShortName)
これを、
Me.CB_Country_ID.SelectedValue = dt.Rows(n).Item("Country_ID").ToString()
こうして下さい。- 回答としてマーク yksaila 2012年4月26日 5:18
-
ただ、フォーム表示の際、サーバーデータの1行目だけがCountryShortNameにならず、 Country_IDになるのです。
例:Japan-- CountryShortName=’JPN’、Country_ID=’1’、CountryCode=’81’
USA-- CountryShortName=’USA’、Country_ID=’2’、CountryCode=’1’
ITALY-- CountryShortName=’ITA、Country_ID=’3’、CountryCode=’39’
この例で、JAPANだけは’1’が表示され、他はUSA,ITAと表示します。 JAPANだけコンボ表示が、CountryShortNameにならず、 Country_IDになるようです。
他は(USA,ITALY)はきちんと表示します(コンボボックスで)。
サーバーデータの表示順を変更しても同じです。 1行目というわけではなく、Country_IDの最初の数字に原因があるようです。
これは実装の問題だと思います。
>>1.表示するとき:
>> 'コンボボックスのデータ:From SERVERテーブル(T_M_Client)
>> Me.CB_Country_ID.Text = dt.Rows(n).Item("Country_ID") ----’サーバーからCountry_IDをひきだしてくる。
>> Me.CB_Country_ID.SelectedValue = Convert.ToString(Me.CB_Country_ID.Text) ----’コンボボックス表示名(CountryShortName)恐らくこれが原因ですね。
Me.CB_Country_ID.Text = dt.Rows(n).Item("Country_ID") ----’サーバーからCountry_IDをひきだしてくる。
Me.CB_Country_ID.SelectedValue = Convert.ToString(Me.CB_Country_ID.Text) ----’コンボボックス表示名(CountryShortName)
これを、
Me.CB_Country_ID.SelectedValue = dt.Rows(n).Item("Country_ID").ToString()
こうして下さい。aviator_さんへ
ありがとうございます。
Me.CB_Country_ID.SelectedValue = dt.Rows(n).Item("Country_ID").ToString() の、一行だけですね。 これで、成功しました。 完璧です。
これで、先へ進めます。 独力では無理でした、感謝しています。
ところで、この行の最後は、.Tostringは、あってもなくても動作します。 どちらが良いのでしょうか? サーバーから引き出したデータは、数値ですし、コンボ表示は文字型ですし?
yksaila
- 回答としてマーク yksaila 2012年4月27日 8:48
-
ところで、この行の最後は、.Tostringは、あってもなくても動作します。 どちらが良いのでしょうか? サーバーから引き出したデータは、数値ですし、コンボ表示は文字型ですし?
セットする先の ComboBox の SelectedValue プロパティはObject型ですので、ToString()は無くても問題ありません。
どちらが良いのでしょうかと言われると微妙ですが、私は型が分かっている物をObject型のまま扱うのが嫌いです。
※今思えば Integer 型で扱うべきな気もしますが・・・別の話としてこれも好き嫌いの部分はありますが、
Me.CB_Country_ID.Text = dt.Rows(n).Item("Country_ID")
を見る限り、プロジェクトのOption Strictオプションが Off になっていると思います。これによりコンパイル時に暗黙的な型変換がなされ、ある意味で型を意識しないでもプログラム出来てしまいます。
※他にもありますが割愛します。しかし、型を意識しないプログラミングは予期せぬバグに繋がりやすい他、レスポンス悪化も起こります。
他にも、VB独自のオプションなのでC#では指定出来ませんし・・・という訳で、型を意識したプログラミングをする事をお勧めします。