- ベストアンサー
VB.NET2003のDataGridでコンボボックス
- VB.NET2003のDataGridでコンボボックスを作成する方法と選択した値の取得方法について調査中です。
- DataGridに異なる値のコンボボックスを行ごとに作成することも可能か確認中です。
- VB.NET2003のDataGridでコンボボックスを作成する方法について知りたいです。また、選択した値を取得する方法や行ごとに異なる値のコンボボックスを作成する方法についても教えてください。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
>行ごとに違うリストのコンボボックスを表示させたいのです それもDOBONさんのクラスを改造したら可能です。 あまり難しく考えず、コードをよく見てみましょうね^^; この手のオブジェクト継承は、難しく捉われがちですが、 DOBONさんのサンプルは非常によくまとまっているし、 デバッグしたら、それほぞ難しいことはしておりません。 コメントも付いてるし。。。。 改造は[DataGridComboBoxColumn]クラス部だけでよいです。 [DataGridComboBox]はそのままです。 -------------------------------------------------------------------------------- Public Class DataGridComboBoxColumn Inherits DataGridTextBoxColumn Private _comboBox() As DataGridComboBox Private _sorce As CurrencyManager Private _rowNumber As Integer Private _editing As Boolean '/ <summary> '/ DataGridComboBoxColumnのコンストラクタ '/ </summary> '/ <param name="dataSource">ComboBoxのDataSource</param> '/ <param name="displayMember">ComboBoxのDisplayMember</param> '/ <param name="valueMember">ComboBoxのValueMember</param> Public Sub New( _ ByVal dataSource() As DataView, _ ByVal displayMember As String, _ ByVal valueMember As String) '初期設定 _sorce = Nothing _editing = False ReDim _comboBox(dataSource.Length - 1) Dim l_combo As DataGridComboBox Dim i As Integer For i = 0 To _comboBox.Length - 1 Call myNew(_comboBox(i), dataSource(i), displayMember, valueMember) Next End Sub 'プロパティ '/ <summary> '/ 管理されている ComboBox コントロールを取得します。 '/ </summary> Public ReadOnly Property ComboBox() As DataGridComboBox Get Return GetActiveCombobox(_rowNumber) End Get End Property 'ComboBoxからフォーカスが離れた Private Sub _comboBox_Leave(ByVal sender As Object, _ ByVal e As EventArgs) If _editing Then 'ComboBoxが編集中だったとき _editing = False '行の値を更新する SetColumnValueAtRow(_sorce, _rowNumber, _ GetActiveCombobox(_rowNumber).Text) Invalidate() End If 'ComboBoxを隠す GetActiveCombobox(_rowNumber).Visible = False 'DataGridのスクロールイベントを捕捉する AddHandler DataGridTableStyle.DataGrid.Scroll, _ AddressOf DataGrid_Scroll End Sub 'DataGridがスクロール Private Sub DataGrid_Scroll(ByVal sender As Object, _ ByVal e As EventArgs) 'ComboBoxを消す If GetActiveCombobox(_rowNumber).Visible Then GetActiveCombobox(_rowNumber).Visible = False End If End Sub 'ComboBoxで選択した項目が変更されて、その変更がコミットされた Private Sub _comboBox_SelectionChangeCommitted( _ ByVal sender As Object, ByVal e As EventArgs) _editing = True 'DataGridに列が編集開始されたことを知らせる MyBase.ColumnStartedEditing(CType(sender, Control)) End Sub '行の最小の高さ Protected Overrides Function GetMinimumHeight() As Integer Return GetActiveCombobox(_rowNumber).PreferredHeight End Function 'ComboBoxをDataGridのControl.ControlCollectionに追加する Protected Overrides Sub SetDataGridInColumn( _ ByVal value As DataGrid) MyBase.SetDataGridInColumn(value) Dim l_combo As DataGridComboBox For Each l_combo In _comboBox l_combo.Parent = CType(value, Control) Next End Sub '列が管理しているコントロールへのフォーカスを '放棄する必要があることを列に通知 Protected Overrides Sub ConcedeFocus() MyBase.ConcedeFocus() GetActiveCombobox(_rowNumber).Visible = False End Sub ''編集するためにセルを準備する Protected Overloads Overrides Sub Edit( _ ByVal source As CurrencyManager, _ ByVal rowNum As Integer, _ ByVal bounds As Rectangle, _ ByVal [readOnly] As Boolean, _ ByVal instantText As String, _ ByVal cellIsVisible As Boolean) '基本クラスのEditを呼び出す MyBase.Edit(source, rowNum, bounds, [readOnly], _ instantText, cellIsVisible) 'TextBoxを消す Me.TextBox.Visible = False '値の保存 _rowNumber = rowNum _sorce = source '表示させるComboBoxの設定をする GetActiveCombobox(rowNum).Bounds = bounds GetActiveCombobox(rowNum).RightToLeft = _ Me.DataGridTableStyle.DataGrid.RightToLeft '非表示、読み取り専用のときは、ComboBoxを表示しない If cellIsVisible AndAlso Not [readOnly] Then 'ComboBoxを表示 GetActiveCombobox(rowNum).Visible = True GetActiveCombobox(rowNum).BringToFront() GetActiveCombobox(rowNum).Focus() End If '選択項目の変更 'ComboBoxを表示する前に行うと、 '新しい行で値を変更した時不都合が起きる GetActiveCombobox(rowNum).SelectedIndex = _ GetActiveCombobox(rowNum).FindStringExact(Me.TextBox.Text) 'DataGridのスクロールイベントを捕捉する AddHandler DataGridTableStyle.DataGrid.Scroll, _ AddressOf DataGrid_Scroll End Sub '編集プロシージャを完了する Protected Overrides Function Commit( _ ByVal dataSource As CurrencyManager, _ ByVal rowNum As Integer) As Boolean If _editing Then '編集中のときは、rowNum行の値を設定する _editing = False SetColumnValueAtRow(dataSource, rowNum, _ GetActiveCombobox(rowNum).Text) End If Return True End Function '指定した行の値を設定 Protected Overrides Sub SetColumnValueAtRow( _ ByVal source As CurrencyManager, _ ByVal rowNum As Integer, ByVal value As Object) 'ValueMemberの値を設定する MyBase.SetColumnValueAtRow(source, rowNum, _ GetActiveCombobox(rowNum).FindValueMember(value)) End Sub '指定した行の値を取得 Protected Overrides Function GetColumnValueAtRow( _ ByVal source As CurrencyManager, _ ByVal rowNum As Integer) As Object Dim val As Object = _ MyBase.GetColumnValueAtRow(source, rowNum) 'DisplayMemberの値を返す Return GetActiveCombobox(rowNum).FindDisplayMember(val) End Function 'NEW用の関数 Private Sub myNew( _ ByRef _combo As DataGridComboBox, _ ByVal dataSource As DataView, _ ByVal displayMember As String, _ ByVal valueMember As String) 'DataGridComboBoxの作成 _combo = New DataGridComboBox() 'ComboBoxの設定 _combo.DropDownStyle = ComboBoxStyle.DropDownList _combo.Visible = False 'データソースの設定 _combo.DataSource = dataSource _combo.DisplayMember = displayMember _combo.ValueMember = valueMember 'イベントハンドラ AddHandler _combo.Leave, AddressOf _comboBox_Leave AddHandler _combo.SelectionChangeCommitted, _ AddressOf _comboBox_SelectionChangeCommitted End Sub '配列要素からN(ROW)番を考慮し、データグリッドコンボボックスを返却する Private Function GetActiveCombobox(ByVal rowNum As Integer) As DataGridComboBox Dim l_index As Integer = (rowNum Mod _comboBox.Length) Return _comboBox(l_index) End Function End Class -------------------------------------------------------------------------------- 画面側は、DATAVIEWを配列で渡します。 下のサンプルは配列要素2ですが、いくつでも良いです。 -------------------------------------------------------------------------------- Dim dt As New DataTable("DataTable1") dt.Columns.Add("Column1", GetType(Integer)) dt.Rows.Add(New Object() {5}) dt.Rows.Add(New Object() {9}) dt.Rows.Add(New Object() {3}) dt.Rows.Add(New Object() {1}) dt.Rows.Add(New Object() {4}) dt.Rows.Add(New Object() {3}) dt.Rows.Add(New Object() {7}) dt.Rows.Add(New Object() {6}) dt.Rows.Add(New Object() {10}) 'DataGridで表示するデータソースに設定 DataGrid1.DataSource = dt 'DataGridTableStyleの作成 Dim ts As New DataGridTableStyle() ts.MappingName = "DataTable1" 'DataGridComboBoxColumnで使用するDataTableの作成 '"DisplayMember"列はComboBoxに表示される値 '"ValueMember"列は実際の値 Dim comboSorce1 As New DataTable("ComboBox") With comboSorce1 .Columns.Add("DisplayMember", GetType(String)) .Columns.Add("ValueMember", GetType(Integer)) .Rows.Add(New Object() {"一", 1}) .Rows.Add(New Object() {"二", 2}) .Rows.Add(New Object() {"三", 3}) .Rows.Add(New Object() {"四", 4}) .Rows.Add(New Object() {"五", 5}) .Rows.Add(New Object() {"六", 6}) .Rows.Add(New Object() {"七", 7}) .Rows.Add(New Object() {"八", 8}) .Rows.Add(New Object() {"九", 9}) .Rows.Add(New Object() {"十", 10}) End With Dim comboSorce2 As DataTable = comboSorce1.Clone With comboSorce2 .Rows.Add(New Object() {"(1)", 1}) .Rows.Add(New Object() {"(2)", 2}) .Rows.Add(New Object() {"(3)", 3}) .Rows.Add(New Object() {"(4)", 4}) .Rows.Add(New Object() {"(5)", 5}) .Rows.Add(New Object() {"(6)", 6}) .Rows.Add(New Object() {"(7)", 7}) .Rows.Add(New Object() {"(8)", 8}) .Rows.Add(New Object() {"(9)", 9}) .Rows.Add(New Object() {"(10)", 10}) End With Dim l_dvw() As DataView = New DataView() {comboSorce1.DefaultView, comboSorce2.DefaultView} 'DataGridComboBoxColumnの作成 Dim cbc As New Dobon.Samples.Forms.DataGridComboBoxColumn( _ l_dvw, "DisplayMember", "ValueMember") cbc.MappingName = "Column1" cbc.HeaderText = "数字" '列スタイルの追加 ts.GridColumnStyles.Add(cbc) 'テーブルスタイルの追加 DataGrid1.TableStyles.Add(ts) -------------------------------------------------------------------------------- コンボボックスの切り替えは、 DataGridComboBoxColumn.GetActiveCombobox にて行っております。 法則を変更したければ、そちらを改造してください。
その他の回答 (1)
- 1050 円(@1050YEN)
- ベストアンサー率69% (477/687)
>CStr(DataGrid1(row,col)) これは画面を見ているだけなので、グリッドのデータソースへの反映値を読んだらいいです。 ついでなので、値からDOBONさんのクラスを利用した変換方法も書いておきます。 Dim l_tbl As DataTable = DirectCast(DataGrid1.DataSource, DataTable) Dim i, j As Integer Dim l_str画面 As String Dim l_str値_GridTable As String Dim l_str値_画面より算出 As String Dim ts As DataGridTableStyle Dim cbc As Dobon.Samples.Forms.DataGridComboBoxColumn Dim cb As Dobon.Samples.Forms.DataGridComboBox Dim l_strテーブル名 As String = l_tbl.TableName Dim l_strカラム名 As String If Me.DataGrid1.TableStyles.Contains(l_strテーブル名) Then ts = Me.DataGrid1.TableStyles(l_strテーブル名) Else MsgBox("スタイル設定なし") Return End If For i = 0 To l_tbl.Columns.Count - 1 l_strカラム名 = l_tbl.Columns(i).ColumnName If ts.GridColumnStyles.Contains(l_strカラム名) Then cbc = ts.GridColumnStyles(l_strカラム名) cb = cbc.ComboBox Else l_str値_画面より算出 = "《設定されていません》" cb = Nothing End If For j = 0 To l_tbl.Rows.Count - 1 '画面上の値 l_str画面 = DataGrid1.Item(j, i) 'Gridのテーブルの反映値 l_str値_GridTable = l_tbl.Rows(j).Item(i).ToString If Not (cb Is Nothing) Then '値からクラスを利用して、求めた値 l_str値_画面より算出 = cb.FindValueMember(l_str画面) End If Console.WriteLine( _ "ROW={0}:COL{1}:表示は{2}:Gridの値は{3}:表示から変換した値は{4}" _ , j, i _ , l_str画面 _ , l_str値_GridTable _ , l_str値_画面より算出 _ ) Next Next それと、 >毎に違う値(リストデータ)のコンボボックスを作成 できます。 グリッドに2列目を作成。さらにその2列目用のスタイルを作成しマッピングしてあげたらよいです。
お礼
わざわざコードまでご丁寧にありがとうございます! おかげさまで値の取得ができました! >>毎に違う値(リストデータ)のコンボボックスを作成 >できます。 >グリッドに2列目を作成。さらにその2列目用のスタイルを>作成しマッピングしてあげたらよいです。 えっと、すみません。 行ごとに違うリストのコンボボックスを表示させたいのです。 別の列に違うコンボボックスを表示するのはできてるのですが、1つの列内の違う行に表示させることはできますでしょうか?
お礼
ありがとうございました! できました!! 本当にお世話になりました。 >あまり難しく考えず、コードをよく見てみましょうね^^; そうですね^^; 反省・・・。 じっくりコードを見直して勉強します!