Solved

VB.Net ComboBox in a Datagrid

Posted on 2004-08-26
19
1,195 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: 11906061
0
 
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
 
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 500 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
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
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

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Article by: jpaulino
XML Literals are a great way to handle XML files and the community doesn’t use it as much as it should.  An XML Literal is like a String (http://msdn.microsoft.com/en-us/library/system.string.aspx) Literal, only instead of starting and ending with w…
It’s quite interesting for me as I worked with Excel using vb.net for some time. Here are some topics which I know want to share with others whom this might help. First of all if you are working with Excel then you need to Download the Following …
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

747 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

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now