DOBON.NET DOBON.NETプログラミング掲示板過去ログ

コントロール(Combobox)配列のDataSourceに同じ値を設定したい

環境/言語:[Windows 7]
分類:[.NET]

コントロール(Combobox)配列のDataSourceに同じ値を設定したくて、
VB.net 2010で以下の様なプログラムを組みました。
「おぉ、俺にも出来た!Visual Basicって簡単っ」と思いきや、
どのコンボボックスの値を変更しても、全てのコンボボックスに
反映されてしまいます。


この現象を解決するにはdtMemberも配列にしてやらなければ
ダメなんでしょうかねぇ?


_/_/_/ 以下ソースコード _/_/_/_/_/_/_/_/_/_/
Imports System.Text

Public Class Form1

    Private cboUser() As ComboBox
    Private dtMember As DataTable

    Private Enum GenericResult As Integer
        Success = 0
        Failed = 1
    End Enum

    Private Const ConfigFileName As String = "init.xml"     '設定ファイル
    Private Const INIT_FILE As String = "設定ファイル"
    Private Const INIT_FILE_READ_ERR_MSG As String = INIT_FILE & "の読み込みに失敗しました。"

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load

        '設定ファイルより情報取得
        If ReadSetting(ConfigFileName).Equals(GenericResult.Failed) Then
            MsgBox(INIT_FILE_READ_ERR_MSG, MsgBoxStyle.Critical, "エラー")
            End
        End If

        'コントロール配列の作成
        cboUser = New ComboBox(19) {}

        With Me
            'コントロールレイアウト中断
            .SuspendLayout()
            .Size = New Size(800, 600)

            'コントロールのインスタンスを作成し、プロパティを設定する
            For i As Integer = 0 To cboUser.Length - 1
                cboUser(i) = New ComboBox
                'プロパティ設定
                With .cboUser(i)
                    .Name = "cboUser" + i.ToString()
                    .DropDownStyle = ComboBoxStyle.DropDown
                    .Font = New Font("MS ゴシック", 12, FontStyle.Regular, GraphicsUnit.Point)
                    .Size = New Size(184, 24)
                    .IntegralHeight = False
                    .ImeMode = ImeMode.Hiragana
                    .MaxDropDownItems = 8
                    .Location = New Point(36, i * 25 + 20)
                    .MaxLength = 20
                    .DisplayMember = "Name"
                    .DataSource = dtMember
                    TabIndex = i
                    AddHandler .KeyPress, AddressOf Me.cboUser_KeyPress
                End With
            Next
            'パネルにコントロールを追加
            .Controls.AddRange(cboUser)

            'コントロールレイアウト再開
            .ResumeLayout(False)
        End With

    End Sub

    Private Function ReadSetting(ByVal _settingfile As String) As GenericResult
        Dim dataSet As New DataSet

        Try
            'dataSet.ReadXml(_settingfile)
            'dtMember = dataSet.Tables("Member")

            Dim dr As DataRow
            Dim strName() As String = {"鈴木一郎", "坂上二郎", "北島三郎", "伊東四郎"}
            Dim strBelong() As String = {"愛知", "鹿児島", "北海道", "ニン"}

            dtMember = New DataTable

            dtMember.Columns.Add("Name")
            dtMember.Columns.Add("Belong")

            For i = 0 To strName.Length - 1
                dr = dtMember.NewRow
                dr("Name") = strName(i)
                dr("Belong") = strBelong(i)
                dtMember.Rows.Add(dr)
            Next

            dtMember.Rows.InsertAt(dtMember.NewRow, 0)

        Catch ex As Exception
            Return GenericResult.Failed
        End Try

        Return GenericResult.Success

    End Function

    'ComboBoxのKeyPressイベントハンドラ
    Private Sub cboUser_KeyPress(sender As Object, e As System.Windows.Forms.KeyPressEventArgs)

        If Encoding.GetEncoding("Shift_JIS").GetByteCount(sender.text) >= 20 Then
            If Asc(e.KeyChar) = Keys.Back Then
                'Backspaceは許す
                e.Handled = False
            Else
                '入力できなくする
                e.Handled = True
            End If
        End If

    End Sub

End Class
■No31700に返信(ぴちさんの記事)

> この現象を解決するにはdtMemberも配列にしてやらなければ
> ダメなんでしょうかねぇ?
配列でなくてもよいですがインスタンスが違うものでないと
同期してしまいます。

dtMemer.Copyでインスタンスのコピーを作るのが楽かと思います。
BindingSourceを使えば、現在位置の共有はされなくなります。

Dim source As New BindingSource()
source.DataSource = dtMember
.DataSource = source

あるいは、別々のDataViewをデータソースにします。

.DataSource = new DataView(dtMember)
ほわーーー、ありがとうございます。

.DataSource = dtMember

.DataSource = dtMember.Copy
または
.DataSource = New DataView(dtMember)
に変更する、もしくは
Dim source As New BindingSource()
source.DataSource = dtMember
.DataSource = source
とすることにより、思い描いていた通りの動作を
実現することが出来ました。目から鱗でございます。


で、どれを採用するべきか?・・・・・・
明確な理由は無いけど、なんとなくの好みで行けば
.DataSource = New DataView(dtMember)
かなぁ〜?


しかし、今回「自分の知識のみでは無理だけど、
きっと簡単に出来ると思う・・・」とGoogle先生に
「VB .net コントロール配列 DataSource 設定 同一」
とかでお伺いを立てたんだけど。解決策に辿り着く
ことが出来ませんでした。

これからVB.Netの知識を吸収して行けば、
検索キーワード選定のセンスも磨かれるものなんですかね?
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板