Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

VB.Net ComboBox in a Datagrid

Posted on 2004-08-26
19
Medium Priority
?
1,235 Views
Last Modified: 2008-01-09
I need to place a combobox into my datagrid.
The values in the combobox will come from a dataset "Table XcomList"
The datagrid will be bound to Table BigData

the value selected in the combobox should be placed in the dataset Bigdata.
0
Comment
Question by:Vartana
  • 9
  • 7
  • 3
19 Comments
 
LVL 8

Expert Comment

by:wguerram
ID: 11906086
0
 
LVL 1

Author Comment

by:Vartana
ID: 11906112
Is there a free component that has this feature built in ?
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 35

Expert Comment

by:YZlat
ID: 11906181
create two vb files: NoKeyUpCombo.vb and DataGridComboBoxColumn.vb

NoKeyUpCombo.vb
_______________________________

Option Strict Off
Option Explicit On

Imports Microsoft.VisualBasic
Imports System
Imports System.ComponentModel
Imports System.Data
Imports System.Data.Common
Imports System.Data.OleDb
Imports System.Drawing
Imports System.Windows.Forms

Namespace DataGridTextBoxCombo
    Public Class NoKeyUpCombo
        Inherits ComboBox
        Private WM_KEYUP As Integer = &H101


        Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
            If m.Msg = WM_KEYUP Then
                'ignore keyup to avoid problem with tabbing & dropdownlist;
                Return
            End If
            MyBase.WndProc(m)
        End Sub 'WndProc
    End Class 'NoKeyUpCombo
End Namespace


DataGridComboBoxColumn.vb
________________________________
Option Strict Off
Option Explicit On

Imports Microsoft.VisualBasic
Imports System
Imports System.ComponentModel
Imports System.Data
Imports System.Data.Common
Imports System.Data.OleDb
Imports System.Drawing
Imports System.Windows.Forms

Namespace DataGridTextBoxCombo
    ' Step 1. Derive a custom column style from DataGridTextBoxColumn
    '      a) add a ComboBox member
    '  b) track when the combobox has focus in Enter and Leave events
    '  c) override Edit to allow the ComboBox to replace the TextBox
    '  d) override Commit to save the changed data
    Public Class DataGridComboBoxColumn
        Inherits DataGridTextBoxColumn
        Public ColumnComboBox As NoKeyUpCombo
        Private _source As System.Windows.Forms.CurrencyManager
        Private _rowNum As Integer
        Private _isEditing As Boolean
        Public Shared _RowCount As Integer


        Public Sub New()
            _source = Nothing
            _isEditing = False
            _RowCount = -1

            ColumnComboBox = New NoKeyUpCombo()
            ColumnComboBox.DropDownStyle = ComboBoxStyle.DropDownList

            AddHandler ColumnComboBox.Leave, AddressOf LeaveComboBox
            AddHandler ColumnComboBox.SelectionChangeCommitted, AddressOf ComboStartEditing
        End Sub 'New

        Private Sub HandleScroll(ByVal sender As Object, ByVal e As EventArgs)
            If ColumnComboBox.Visible Then
                ColumnComboBox.Hide()
            End If
        End Sub 'HandleScroll

        Private Sub ComboStartEditing(ByVal sender As Object, ByVal e As EventArgs)
            _isEditing = True
            MyBase.ColumnStartedEditing(sender)
        End Sub 'ComboMadeCurrent


        Private Sub LeaveComboBox(ByVal sender As Object, ByVal e As EventArgs)
            If _isEditing Then
                SetColumnValueAtRow(_source, _rowNum, ColumnComboBox.Text)
                _isEditing = False
                Invalidate()

            End If
            ColumnComboBox.Hide()
            AddHandler Me.DataGridTableStyle.DataGrid.Scroll, New EventHandler(AddressOf HandleScroll)
        End Sub 'LeaveComboBox


        Protected Overloads Overrides Sub Edit(ByVal [source] As System.Windows.Forms.CurrencyManager, ByVal rowNum As Integer, ByVal bounds As System.Drawing.Rectangle, ByVal [readOnly] As Boolean, ByVal instantText As String, ByVal cellIsVisible As Boolean)

            MyBase.Edit([source], rowNum, bounds, [ReadOnly], instantText, cellIsVisible)

            _rowNum = rowNum
            _source = [source]

            ColumnComboBox.Parent = Me.TextBox.Parent
            ColumnComboBox.Location = Me.TextBox.Location
            ColumnComboBox.Size = New Size(Me.TextBox.Size.Width, ColumnComboBox.Size.Height)
            ColumnComboBox.SelectedIndex = ColumnComboBox.FindStringExact(Me.TextBox.Text)
            ColumnComboBox.Text = Me.TextBox.Text
            Me.TextBox.Visible = False
            ColumnComboBox.Visible = True
            AddHandler Me.DataGridTableStyle.DataGrid.Scroll, AddressOf HandleScroll

            ColumnComboBox.BringToFront()
            ColumnComboBox.Focus()
        End Sub 'Edit


        Protected Overrides Function Commit(ByVal dataSource As System.Windows.Forms.CurrencyManager, ByVal rowNum As Integer) As Boolean

            If _isEditing Then
                _isEditing = False
                SetColumnValueAtRow(dataSource, rowNum, ColumnComboBox.Text)
            End If
            Return True
        End Function 'Commit


        Protected Overrides Sub ConcedeFocus()
            Console.WriteLine("ConcedeFocus")
            MyBase.ConcedeFocus()
        End Sub 'ConcedeFocus

        Protected Overrides Function GetColumnValueAtRow(ByVal [source] As System.Windows.Forms.CurrencyManager, ByVal rowNum As Integer) As Object

            Dim s As Object = MyBase.GetColumnValueAtRow([source], rowNum)
            Dim dv As DataView = CType(Me.ColumnComboBox.DataSource, DataView)
            Dim rowCount As Integer = dv.Count
            Dim i As Integer = 0
            Dim s1 As Object

            'if things are slow, you could order your dataview
            '& use binary search instead of this linear one
            While i < rowCount
                s1 = dv(i)(Me.ColumnComboBox.ValueMember)
                If (Not s1 Is DBNull.Value) AndAlso _
                    (Not s Is DBNull.Value) AndAlso _
                            s = s1 Then
                    Exit While
                End If
                i = i + 1
            End While

            If i < rowCount Then
                Return dv(i)(Me.ColumnComboBox.DisplayMember)
            End If
            Return DBNull.Value
        End Function 'GetColumnValueAtRow


        Protected Overrides Sub SetColumnValueAtRow(ByVal [source] As System.Windows.Forms.CurrencyManager, ByVal rowNum As Integer, ByVal value As Object)
            Dim s As Object = value

            Dim dv As DataView = CType(Me.ColumnComboBox.DataSource, DataView)
            Dim rowCount As Integer = dv.Count
            Dim i As Integer = 0
            Dim s1 As Object

            'if things are slow, you could order your dataview
            '& use binary search instead of this linear one
            While i < rowCount
                s1 = dv(i)(Me.ColumnComboBox.DisplayMember)
                If (Not s1 Is DBNull.Value) AndAlso _
                            s = s1 Then
                    Exit While
                End If
                i = i + 1
            End While
            If i < rowCount Then
                s = dv(i)(Me.ColumnComboBox.ValueMember)
            Else
                s = DBNull.Value
            End If
            MyBase.SetColumnValueAtRow([source], rowNum, s)
        End Sub 'SetColumnValueAtRow


    End Class 'DataGridComboBoxColumn


End Namespace







Then do this:

   Dim tableStyle As New DataGridTableStyle()
    tableStyle.MappingName = "BigData"

    Dim dt As DataTable = myDataSet.Tables("BigData")


''..............add other columns here............


                   Dim ComboTextCol As New DataGridComboBoxColumn()
                    ComboTextCol.MappingName = "Field_ID"
                    ComboTextCol.HeaderText = "Header for Combo"
                    ComboTextCol.Width = 120
                   
                    ComboTextCol.ColumnComboBox.DataSource = myDataSet.Tables("BigData").DefaultView
                    ComboTextCol.ColumnComboBox.DisplayMember = "FieldName"
                    ComboTextCol.ColumnComboBox.ValueMember = "Field_ID"


                    tableStyle.PreferredRowHeight = ComboTextCol.ColumnComboBox.Height + 2

                    tableStyle.GridColumnStyles.Add(ComboTextCol)
0
 
LVL 1

Author Comment

by:Vartana
ID: 11906979
I did that but my datagrid is empty
0
 
LVL 1

Author Comment

by:Vartana
ID: 11907179
YZlat
Above post is for you
0
 
LVL 1

Author Comment

by:Vartana
ID: 11907245
I used Me.EntryGrid.TableStyles.Add(tableStyle) at the end and it still does not work
0
 
LVL 8

Accepted Solution

by:
wguerram earned 2000 total points
ID: 11907351
http://www.syncfusion.com/faq/winforms/Files/datagridtextboxcombo_vb.zip

This is the project,

Just open it and run it.
0
 
LVL 1

Author Comment

by:Vartana
ID: 11907755
can i do it even if i bind to mydataset ?
0
 
LVL 8

Expert Comment

by:wguerram
ID: 11907868
The class DataGridComboBoxColumnExpose the ComboBox as a public member so you can access it this way:

dim c as new DataGridComboBoxColumn

c.ColumnComboBox

You can add a list manually or assign the valuse from the Dataset
0
 
LVL 1

Author Comment

by:Vartana
ID: 11907961
wguerram,

    I have a dataset that my datagrid is bound to. Now i want to add 1 more column manually that will be a combo box that will get its information from another dataset and whatever value that gets selected will be inputed into the other dataset.
0
 
LVL 8

Expert Comment

by:wguerram
ID: 11908072
Just set the combobox to the new table

c.ColumnComboBox.DataSource = myDataSet2.Tables(0)
c.ComboTextCol.ColumnComboBox.ValueMember = "custName"
c.ColumnComboBox.ValueMember = "custName"

Data will be inputed in MyDataSet
0
 
LVL 1

Author Comment

by:Vartana
ID: 11908095
yeah but the combo box wont even show up in my datagrid
0
 
LVL 8

Expert Comment

by:wguerram
ID: 11908117
Let's make this clear.

I have DataSet1 which is bound to a DataGrid, let's supposed it has 3 columns.

You have DataSet2
Which is bound to the combobox in order to show a list of values


You want to add a new column, to the DataGrid, this column will be added to DataSet1 too.?
0
 
LVL 1

Author Comment

by:Vartana
ID: 11908127
yes and it will be a Combobox which gets it values from dataset2
0
 
LVL 8

Expert Comment

by:wguerram
ID: 11908176
Could you run the project which adds a ComboBox?

If so, now you know how to add a ComboBox column.

This method add the combobox to the datagrid

AddCustomDataTableStyle

there you should set the DataSource of The ComboBox to Dataset2

ComboTextCol.ColumnComboBox.Items.Clear()
ComboTextCol.ColumnComboBox.DataSource = myDataSet2.Tables(0)
ComboTextCol.ColumnComboBox.ValueMember = "MyColumn"

The list will show MyColumn from Dataset, but the display member will be the one in the dataGrid or Dataset1
0
 
LVL 35

Expert Comment

by:YZlat
ID: 11911963
Vartana, please post all the column names that you want displayed in the grid and also post the structure of your database table.
What database are you using? Access? SQL?
0
 
LVL 1

Author Comment

by:Vartana
ID: 11915290
SQL

"Dataset = "MyDataset_A"
"Table= "RamTable"
<xs:element name="Account" type="xs:string" minOccurs="0" />
<xs:element name="BillToName" type="xs:string" minOccurs="0" />
<xs:element name="PaymentType" type="xs:int" minOccurs="0" />
<xs:element name="PaymentAmount" type="xs:double" minOccurs="0" />
<xs:element name="PaymentDate" type="xs:date" minOccurs="0" />
<xs:element name="CheckNumber" type="xs:long" minOccurs="0" />
<xs:element name="ChangeAddress" type="xs:int" minOccurs="0" />

I want the "ACCOUNT" to be a drop down combobox  

"Dataset = "MyDataset_A"
"Table= "AccountInformation"
<xs:element name="Account" type="xs:string" minOccurs="0" />
<xs:element name="CustomerName" type="xs:string" minOccurs="0" />

when they select the account it should input the "Account" value into Ramtable "Account" and the CustomerName into RamTable "BillToName"



0
 
LVL 35

Expert Comment

by:YZlat
ID: 11915856
In addition to the two files that I provided earlier, create frmAccount.vb Win Form and put the datagrid control (call it "MyGrid") and the following code there:

Imports System
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Data
Imports System.Data.OleDb

Namespace DataGridTextBoxCombo

   
    Public Class frmAccount
        Inherits System.Windows.Forms.Form
        Private myDataSet As DataSet
        Private dataAdapter As OleDbDataAdapter
 
        Private components As System.ComponentModel.Container = Nothing


        Private Sub MakeDataSetAndBindGrid()
            ' Set the connection and sql strings
            ' assumes your mdb file is in your root
            Dim connString As String = "Provider=Microsoft.JET.OLEDB.4.0;data source=Server.MapPath(MyDatabase.mdb)"
            Dim sqlString As String = "SELECT * FROM RamTable"

            DataAdapter = Nothing
            myDataSet = Nothing

            Try
                ' Connection object
                Dim connection As New OleDbConnection(connString)

                ' Create data adapter object
                DataAdapter = New OleDbDataAdapter(sqlString, connection)

                ' Create a dataset object and fill with data using data adapter's Fill method
                myDataSet = New DataSet()
                dataAdapter.Fill(myDataSet, "RamTable")


               
            Catch ex As Exception
                MessageBox.Show(("Problem with DB access-   connection: " + connString + " query: " + sqlString + ex.ToString()))
                Me.Close()
                Return  
          Finally
            connection.Close()
            End Try

            ' Create a table style that will hold the new column style
            ' that we set and also tie it to our customer's table from our DB
            Dim tableStyle As New DataGridTableStyle()
            tableStyle.MappingName = "RamTable"

            Dim dt As DataTable = myDataSet.Tables("RamTable")

            ' make the dataGrid use our new tablestyle and bind it to our table
            Dim i As Integer

            While i < dt.Columns.Count
               

                if i=1 Then
                    Dim ComboTextCol As New DataGridComboBoxColumn()
                    ComboTextCol.MappingName = "Account"
                    ComboTextCol.HeaderText = "Account"
                    ComboTextCol.Width = 120
   
                    ComboTextCol.ColumnComboBox.DataSource = myDataSet.Tables("RamTable").DefaultView
                    ComboTextCol.ColumnComboBox.DisplayMember = "Account"
                    ComboTextCol.ColumnComboBox.ValueMember = "Account"


                    tableStyle.PreferredRowHeight = ComboTextCol.ColumnComboBox.Height + 2

                    tableStyle.GridColumnStyles.Add(ComboTextCol)
            else
                  Dim TextCol As New DataGridTextBoxColumn()
                    TextCol.MappingName = dt.Columns(i).ColumnName
                    TextCol.HeaderText = dt.Columns(i).ColumnName
                    tableStyle.GridColumnStyles.Add(TextCol)
                End If
                i = i + 1
            End While

            MyGrid.TableStyles.Clear()
            MyGrid.TableStyles.Add(tableStyle)
            MyGrid.DataSource = dt


            'make it no append
            myDataSet.Tables("RamTable").DefaultView.AllowDelete = False
            myDataSet.Tables("RamTable").DefaultView.AllowNew = False
            myDataSet.Tables("RamTable").DefaultView.AllowEdit = False
        End Sub 'MakeDataSetAndBindGrid

    End Class 'Form1
End Namespace 'DataGridTextBoxCombo
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

If you're writing a .NET application to connect to an Access .mdb database and use pre-existing queries that require parameters, you've come to the right place! Let's say the pre-existing query(qryCust) in Access takes a Date as a parameter and l…
Introduction As chip makers focus on adding processor cores over increasing clock speed, developers need to utilize the features of modern CPUs.  One of the ways we can do this is by implementing parallel algorithms in our software.   One recent…
Despite its rising prevalence in the business world, "the cloud" is still misunderstood. Some companies still believe common misconceptions about lack of security in cloud solutions and many misuses of cloud storage options still occur every day. …
Is your OST file inaccessible, Need to transfer OST file from one computer to another? Want to convert OST file to PST? If the answer to any of the above question is yes, then look no further. With the help of Stellar OST to PST Converter, you can e…

782 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question