Vb.net 如何为每个记录的DataGridViewComboBox分配不同的数据源?

Vb.net 如何为每个记录的DataGridViewComboBox分配不同的数据源?,vb.net,winforms,datagridview,combobox,Vb.net,Winforms,Datagridview,Combobox,我有一个winforms DataGridView,我希望有一个包含每个记录的组合框的列。每一个组合框对于每一行都有完全不同的值,并且需要在DataGridView的数据绑定期间分配一个数据源。我可以为所有这些简单的操作分配一个数据源,但是让每个组合框具有不同的值看起来是不可能的 以下是我正在使用的内容-注意:DataGridView的数据源是通过从调用表单设置属性以编程方式定义的 Public Class frmSendToQuickbooksPopup Public Propert

我有一个winforms DataGridView,我希望有一个包含每个记录的组合框的列。每一个组合框对于每一行都有完全不同的值,并且需要在DataGridView的数据绑定期间分配一个数据源。我可以为所有这些简单的操作分配一个数据源,但是让每个组合框具有不同的值看起来是不可能的

以下是我正在使用的内容-注意:DataGridView的数据源是通过从调用表单设置属性以编程方式定义的

Public Class frmSendToQuickbooksPopup

    Public Property CurrentOrder As OrderICT
    Public Property lineitems As List(Of OrderLineItemICT)

    Private Sub frmSendToQuickbooksPopup_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        'define the combobox (datasource can't be assigned here as each will be different for each row)
        Dim dgvcboMatch As New DataGridViewComboBoxColumn
        dgvcboMatch.DisplayMember = "Name"
        dgvcboMatch.ValueMember = "ListID"
        dgvcboMatch.HeaderText = "Matches"
        dgvcboMatch.Name = "Match"
        dgvcboMatch.Width = 150
        dgvLineItems.Columns.Add(dgvcboMatch)

        Me.dgvLineItems.DataSource = lineitems
    End Sub

    Private Sub dgvLineItems_DataSourceChanged(sender As Object, e As EventArgs) Handles dgvLineItems.DataSourceChanged
        Dim L As New QBI.OrderLineItemICT
        With L
            dgvLineItems.Columns(.col_LineItemBvin).Visible = False
            dgvLineItems.Columns(.col_ProductId).Visible = False
            dgvLineItems.Columns(.col_ProductShortDescription).Visible = False
            dgvLineItems.Columns(.col_ShippingBoxCount).Visible = False
            dgvLineItems.Columns(.col_CustomProperties).Visible = False
            dgvLineItems.Columns(.col_ShippingLength).Visible = False
            dgvLineItems.Columns(.col_ShippingWidth).Visible = False
            dgvLineItems.Columns(.col_ShippingHeight).Visible = False
            dgvLineItems.Columns(.col_ProductName).DisplayIndex = 2
            dgvLineItems.Columns(.col_ProductName).HeaderText = "Product Name"
            dgvLineItems.Columns(.col_ProductName).Width = 170
            dgvLineItems.Columns(.col_ProductSku).HeaderText = "SKU"
            dgvLineItems.Columns(.col_ProductSku).Width = 160
            dgvLineItems.Columns(.col_Quantity).DefaultCellStyle.Format = "n0"
            dgvLineItems.Columns(.col_Quantity).DisplayIndex = 7
            dgvLineItems.Columns(.col_Quantity).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
            dgvLineItems.Columns(.col_Quantity).Width = 65
            dgvLineItems.Columns(.col_AdjustedPrice).DefaultCellStyle.Format = "c2"
            dgvLineItems.Columns(.col_AdjustedPrice).HeaderText = "Adj Price"
            dgvLineItems.Columns(.col_AdjustedPrice).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
            dgvLineItems.Columns(.col_AdjustedPrice).Width = 80
            dgvLineItems.Columns(.col_BasePrice).DefaultCellStyle.Format = "c2"
            dgvLineItems.Columns(.col_BasePrice).HeaderText = "Base Price"
            dgvLineItems.Columns(.col_BasePrice).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
            dgvLineItems.Columns(.col_BasePrice).Width = 85
            dgvLineItems.Columns(.col_Discounts).DefaultCellStyle.Format = "c2"
            dgvLineItems.Columns(.col_Discounts).HeaderText = "Discounts"
            dgvLineItems.Columns(.col_Discounts).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
            dgvLineItems.Columns(.col_Discounts).Width = 80
            dgvLineItems.Columns(.col_LineTotal).DefaultCellStyle.Format = "c2"
            dgvLineItems.Columns(.col_LineTotal).HeaderText = "Line Total"
            dgvLineItems.Columns(.col_LineTotal).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
            dgvLineItems.Columns(.col_LineTotal).Width = 80
            dgvLineItems.Columns(.col_UOM).DisplayIndex = 9
            dgvLineItems.Columns(.col_UOM).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
            dgvLineItems.Columns(.col_UOM).HeaderText = "Units"
            dgvLineItems.Columns(.col_UOM).Width = 55
            dgvLineItems.Columns(.col_ShippingWeight).DisplayIndex = 10
            dgvLineItems.Columns(.col_ShippingWeight).HeaderText = "Unit Wt"
            dgvLineItems.Columns(.col_ShippingWeight).DefaultCellStyle.Format = "N1"
            dgvLineItems.Columns(.col_ShippingWeight).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
            dgvLineItems.Columns(.col_ShippingWeight).Width = 70
        End With
    End Sub

Public Function GetComboboxData(ProductNameToMatch As String, ProductSKUToMatch As String) As List(Of WPM_Item)
    'this function returns a list of returned matches for a given row's ProductName or SKU
    'this function will be the datasource for a given combobox
    Dim itms As New List(Of WPM_Item)
    itms = WPM_Data.FindWPM_ItemMatch(ProductNameToMatch, ProductSKUToMatch)
    Return itms
End Function



End Class
如果有某种方法可以截取DataGridView的数据绑定,这样我就可以从另一个单元格获取一个值来调用另一个过程,然后使用返回数据填充每一行的组合框。这对于webforms来说很简单,但是我没有看到winforms版本的事件

另一件事我试过了,但不起作用,combobox数据源就消失了

Private Sub dgvLineItems_DataBindingComplete(sender As Object, e As DataGridViewBindingCompleteEventArgs) Handles dgvLineItems.DataBindingComplete
    For Each row As DataGridViewRow In Me.dgvLineItems.Rows
        Dim dr = DirectCast(row.DataBoundItem, OrderLineItemICT)
        If dr Is Nothing Then
            Return
        End If

        Dim name As String = row.Cells(dr.col_ProductName).Value.ToString
        Dim SKU As String = row.Cells(dr.col_ProductSku).Value.ToString

        Dim cell As DataGridViewComboBoxCell = TryCast(row.Cells("Match"), DataGridViewComboBoxCell)
        cell.DisplayStyle = DataGridViewComboBoxDisplayStyle.ComboBox

        Dim wpm_items As List(Of WPM_Item) = GetComboboxData(name, SKU)
        If cell.DataSource Is Nothing Then
            cell.DataSource = wpm_items 'this forgets the datasource, why?
            cell.DisplayMember = "Name"
            cell.ValueMember = "ListID"
            cell.Value = wpm_items.Item(0).Name 'this always throws an error "DataGridViewComboBoxCell value is not valid."
        End If

    Next

End Sub
这是同一个赋值的另一个版本,这次用add方法填充组合框。仍然不记得这些值 我基本上遵循了另一个论坛的想法——也许Dotnet4.5DataGridView有一个bug

Private Sub dgvLineItems_DataBindingComplete(sender As Object, e As DataGridViewBindingCompleteEventArgs) Handles dgvLineItems.DataBindingComplete
    For Each row As DataGridViewRow In Me.dgvLineItems.Rows
        Dim dr = DirectCast(row.DataBoundItem, OrderLineItemICT)
        If dr Is Nothing Then
            Return
        End If

        Dim name As String = row.Cells(dr.col_ProductName).Value.ToString
        Dim SKU As String = row.Cells(dr.col_ProductSku).Value.ToString

        Dim cell As DataGridViewComboBoxCell = DirectCast(row.Cells("Match"), DataGridViewComboBoxCell)
        cell.DisplayStyle = DataGridViewComboBoxDisplayStyle.ComboBox

        Dim wpm_items As List(Of WPM_Item) = GetComboboxData(name, SKU)

        'THIS DOES NOT WORK EITHER!! 
        cell.DisplayMember = "Name"
        cell.ValueMember = "ListID"
        For Each wItm As WPM_Item In wpm_items
            Dim c As New comboboxitem
            c.Text = wItm.Name
            c.Value = wItm.ListID
            cell.Items.Add(c)
        Next
    Next
End Sub
Public Class ComboboxItem
    Public Property Text() As String
    Public Property Value() As Object

    Public Overrides Function ToString() As String
        Return Text
    End Function
End Class

下面是一个C语言示例,介绍如何在DataGridView中使用不同类型的DataGridViewComboBoxColumn

解决方案

使用DataBindingComplete事件处理程序迭代行,并为每个DataGridViewComboxCell设置源

范例

下面是我如何做到这一点的一个例子。您需要添加一个DataGridView和一个带有两个选项的组合框,即选项1和选项2,用于将DataGridView.DataSource切换到表单


那好吧!这里有一个有效的解决方案。我发现,您必须以编程方式创建DataGridView,这很单调,是的!并关闭自动生成列-这可以防止多次触发dataGridView事件。它还可以防止丢失组合框的数据源。使用DataBindingComplete事件并解析其中的行是执行此操作的最佳方法。格式化事件是一种过度杀伤力,称为w/每次鼠标移动、单击、调整大小等。 对于我们这些使用对象而不是数据表的人,我希望这个解决方案是可用的

守则:

Imports QBI
Imports QBI.QBI
Imports QBI.AppCore.Xutilities

Public Class TestDGV1

    Public dgv1 As DataGridView

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

        Dim ordlineitems As List(Of OrderLineItemICT)
        ordlineitems = Order_DataICT.GetNewOrderLineItemsICT("26073bff-3a08-4bc2-8da9-79c75534bd6b")
        dgv1 = Me.CreateDGV(ordlineitems) 'create the DataGridView and save it as "dgv1" (which must be publically accessible)

        Me.SplitContainer1.Panel2.Controls.Add(dgv1) 'NOTE, the datagridview is inside a SplitContainer
    End Sub

    Public Function CreateDGV(dsItems As List(Of OrderLineItemICT)) As DataGridView
        Dim dgv As New DataGridView()
        dgv.Dock = DockStyle.Fill
        dgv.DataSource = dsItems
        dgv.EditMode = DataGridViewEditMode.EditOnEnter
        dgv.AutoGenerateColumns = False
        dgv.AllowUserToAddRows = False

        Dim L As New QBI.OrderLineItemICT 'only using this reference for my column names defined elsewhere

        Dim col0 As New DataGridViewComboBoxColumn With {.Name = "Match", .DataPropertyName = "NameMatch", .DisplayMember = "Name", .ValueMember = "ListID", .HeaderText = "Matches", .AutoComplete = True}
        col0.DisplayIndex = 0

        Dim col1 As New DataGridViewTextBoxColumn With {.Name = L.col_LineItemBvin, .DataPropertyName = L.col_LineItemBvin, .Visible = False, .ReadOnly = True, .HeaderText = L.col_LineItemBvin}
        col1.DisplayIndex = 1

        Dim col2 As New DataGridViewTextBoxColumn With {.Name = L.col_ProductId, .DataPropertyName = L.col_ProductId, .Visible = False, .ReadOnly = True, .HeaderText = L.col_ProductId}
        col2.DisplayIndex = 2

        Dim col3 As New DataGridViewTextBoxColumn With {.Name = L.col_ProductSku, .DataPropertyName = L.col_ProductSku, .Visible = True, .ReadOnly = True, .HeaderText = "SKU"}
        col3.DisplayIndex = 3
        col3.Width = 160
        Dim col4 As New DataGridViewTextBoxColumn With {.Name = L.col_Quantity, .DataPropertyName = L.col_Quantity, .Visible = True, .ReadOnly = True, .HeaderText = "QTY"}
        col4.DisplayIndex = 9
        col4.Width = 65
        col4.DefaultCellStyle.Format = "n0"
        col4.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter

        Dim col5 As New DataGridViewTextBoxColumn With {.Name = L.col_BasePrice, .DataPropertyName = L.col_BasePrice, .Visible = True, .ReadOnly = True, .HeaderText = "Base Price"}
        col5.DisplayIndex = 6
        col5.DefaultCellStyle.Format = "c2"
        col5.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
        col5.Width = 85

        Dim col6 As New DataGridViewTextBoxColumn With {.Name = L.col_Discounts, .DataPropertyName = L.col_Discounts, .Visible = True, .ReadOnly = True, .HeaderText = "Discounts"}
        col6.DisplayIndex = 7
        col6.DefaultCellStyle.Format = "c2"
        col6.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
        col6.Width = 80

        Dim col7 As New DataGridViewTextBoxColumn With {.Name = L.col_AdjustedPrice, .DataPropertyName = L.col_AdjustedPrice, .Visible = True, .ReadOnly = True, .HeaderText = "Adj Price"}
        col7.DisplayIndex = 8
        col7.DefaultCellStyle.Format = "c2"
        col7.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
        col7.Width = 80

        Dim col8 As New DataGridViewTextBoxColumn With {.Name = L.col_LineTotal, .DataPropertyName = L.col_LineTotal, .Visible = True, .ReadOnly = True, .HeaderText = "Line Total"}
        col8.DisplayIndex = 11
        col8.DefaultCellStyle.Format = "c2"
        col8.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
        col8.Width = 80

        Dim col9 As New DataGridViewTextBoxColumn With {.Name = L.col_ProductName, .DataPropertyName = L.col_ProductName, .Visible = True, .ReadOnly = True, .HeaderText = "Product Name"}
        col9.DisplayIndex = 4
        col9.Width = 170

        Dim col10 As New DataGridViewTextBoxColumn With {.Name = L.col_ProductShortDescription, .DataPropertyName = L.col_ProductShortDescription, .Visible = False, .ReadOnly = True, .HeaderText = L.col_ProductShortDescription}
        col10.DisplayIndex = 5

        Dim col11 As New DataGridViewTextBoxColumn With {.Name = L.col_ShippingWeight, .DataPropertyName = L.col_ShippingWeight, .Visible = True, .ReadOnly = True, .HeaderText = "Unit Wt"}
        col11.DisplayIndex = 12
        col11.DefaultCellStyle.Format = "N1"
        col11.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
        col11.Width = 70
        Dim col12 As New DataGridViewTextBoxColumn With {.Name = L.col_ShippingWidth, .DataPropertyName = L.col_ShippingWidth, .Visible = False, .ReadOnly = True, .HeaderText = L.col_ShippingWidth}
        col12.DisplayIndex = 13

        Dim col13 As New DataGridViewTextBoxColumn With {.Name = L.col_ShippingHeight, .DataPropertyName = L.col_ShippingHeight, .Visible = False, .ReadOnly = True, .HeaderText = L.col_ShippingHeight}
        col13.DisplayIndex = 14

        Dim col14 As New DataGridViewTextBoxColumn With {.Name = L.col_ShippingBoxCount, .DataPropertyName = L.col_ShippingBoxCount, .Visible = False, .ReadOnly = True, .HeaderText = L.col_ShippingBoxCount}
        col14.DisplayIndex = 15

        Dim col15 As New DataGridViewTextBoxColumn With {.Name = L.col_CustomProperties, .DataPropertyName = L.col_CustomProperties, .Visible = False, .ReadOnly = True, .HeaderText = L.col_CustomProperties}
        col15.DisplayIndex = 16

        Dim col16 As New DataGridViewTextBoxColumn With {.Name = L.col_UOM, .DataPropertyName = L.col_UOM, .Visible = True, .ReadOnly = True, .HeaderText = "Units"}
        col16.DisplayIndex = 10
        col16.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
        col16.Width = 55

        dgv.Columns.AddRange({col0, col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11, col12, col13, col14, col15, col16})

        AddHandler dgv.DataBindingComplete, AddressOf dgvLineItems_DataBindingComplete

        Return dgv
    End Function

    Private Sub dgvLineItems_DataBindingComplete(sender As Object, e As DataGridViewBindingCompleteEventArgs)
        For Each row As DataGridViewRow In Me.dgv1.Rows
            Dim dr = DirectCast(row.DataBoundItem, OrderLineItemICT)
            If dr Is Nothing Then
                Return
            End If

            Dim name As String = row.Cells(dr.col_ProductName).Value.ToString
            Dim SKU As String = row.Cells(dr.col_ProductSku).Value.ToString
            Dim cell As DataGridViewComboBoxCell = DirectCast(row.Cells("Match"), DataGridViewComboBoxCell)
            Dim wpm_items As List(Of WPM_Item) = GetComboboxData(name, SKU) 'function inside
            If cell.DataSource Is Nothing Then
                cell.DataSource = wpm_items 
                cell.DisplayMember = "Name"
                cell.ValueMember = "ListID"
                cell.Value = cell.Items(0).ListID
            End If
        Next
    End Sub

    Public Function GetComboboxData(ProductNameToMatch As String, ProductSKUToMatch As String) As List(Of WPM_Item)
        'this function returns a list of returned matches for a given row's ProductName or SKU
        'this function will be the datasource for a given combobox
        Dim itms As New List(Of WPM_Item)
        itms = WPM_Data.FindWPM_ItemMatch(ProductNameToMatch, ProductSKUToMatch)
        Return itms
    End Function

End Class

该示例的问题在于,它仅在编辑单元格时有效。在绘制网格时,必须填充组合。好的-看起来事件拦截不起作用。格式化不适合此目的,因为它几乎是连续触发的。它必须是完全手动创建网格并填充值。我在做实验。你说的事件拦截是什么意思?根据我的经验,最困难的部分是让DataGridView通过混合值来停止抛出异常。CellFormatting是可选的,但却是格式化数据的正确方法。这只是为了说明,这件事并不重要。除了在编辑模式下,不可能引用单元格中的控件,只能引用值。换句话说,不可能在网格中的每个组合框绘制时为其分配不同的数据源。我认为解决这个问题的方法是为所有不同的组合框创建所有数据源,然后在代码中创建datagridview,就像您的示例一样。我不介意再次迭代-很好的示例。如何显示DatagridViewComboBox的选定值?实际上,只需要选定的第一项selectedindex=0。环顾互联网,看看这是如何做到的。MS并没有让这变得容易。我得到了row.CellsMatch.Value=???部分,但似乎无法获取ComboxOK的第一个值-到目前为止,无法设置DGVCombox的选定索引!,但是可以设置dgvComboBox使用的单元格本身的值。所以我接近正确答案了。我尝试了此操作,但无效:Dim itm As Group=DirectCastcell.Items0,Group row.CellsMatch.Value=itm.Members0.ToString使用上述代码得到的错误:DataGridViewComboxCell值无效。24小时拉头发,仍然没有解决方案@MC9000非常接近。尝试cell.Value=cell.Items0.Name。我将其添加到上面的代码示例中,当运行时,它给出了所需的结果。我原以为应该是cell.Value=cell.Items0,但有魔力。
Public Class Form1

    Public Property Groups As List(Of Group)

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

        Me.Groups = Me.InitializeGroups()

        Dim cbc As New DataGridViewComboBoxColumn()
        cbc.DisplayMember = "Name"
        cbc.ValueMember = "ID"
        cbc.HeaderText = "Matches"
        cbc.Name = "Match"
        cbc.Width = 150
        Me.DataGridView1.Columns.Add(cbc)

        Me.ComboBox1.SelectedIndex = 0
    End Sub

    Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
        Dim examples As New List(Of Example)()

        If Me.ComboBox1.SelectedIndex = 0 Then
            examples.Add(New Example("Me", "blah"))
            examples.Add(New Example("You", "blah"))
        Else
            examples.Add(New Example("Him", "blah"))
            examples.Add(New Example("Her", "blah"))
            examples.Add(New Example("It", "blah"))
        End If

        Me.DataGridView1.DataSource = examples
    End Sub

    Private Sub DataGridView1_DataBindingComplete(sender As Object, e As DataGridViewBindingCompleteEventArgs) Handles DataGridView1.DataBindingComplete
        For Each row As DataGridViewRow In Me.DataGridView1.Rows
            Dim cell As DataGridViewComboBoxCell = TryCast(row.Cells("Match"), DataGridViewComboBoxCell)
            cell.DataSource = Me.Groups.Where(Function(g) g.Members.Contains(row.Cells("Foo").Value.ToString())).ToList()
            cell.Value = cell.Items(0).ID ' Same property as combocell.ValueMember
        Next
    End Sub

    Private Function InitializeGroups() As List(Of Group)
        Dim groups = New List(Of Group)() From { _
            New Group() With { _
                .ID = 1, _
                .Name = "All", _
                .Members = New List(Of String)() From { _
                    "Me", _
                    "You", _
                    "Him", _
                    "Her", _
                    "It" _
                } _
            }, _
            New Group() With { _
                .ID = 2, _
                .Name = "Them", _
                .Members = New List(Of String)() From { _
                    "Him", _
                    "Her", _
                    "It" _
                } _
            }, _
            New Group() With { _
                .ID = 3, _
                .Name = "Us", _
                .Members = New List(Of String)() From { _
                    "Me", _
                    "You" _
                } _
            }, _
            New Group() With { _
                .ID = 4, _
                .Name = "Me", _
                .Members = New List(Of String)() From { _
                    "Me" _
                } _
            }, _
            New Group() With { _
                .ID = 5, _
                .Name = "Human", _
                .Members = New List(Of String)() From { _
                    "Me", _
                    "You", _
                    "Him", _
                    "Her" _
                } _
            }, _
            New Group() With { _
                .ID = 6, _
                .Name = "Non-human", _
                .Members = New List(Of String)() From { _
                    "It" _
                } _
            } _
        }

        Return groups
    End Function
End Class

Public Class Example
    Public Sub New(foo__1 As String, bar__2 As String)
        Foo = foo__1
        Bar = bar__2
    End Sub

    Public Property Foo() As String
        Get
            Return m_Foo
        End Get
        Set(value As String)
            m_Foo = Value
        End Set
    End Property
    Private m_Foo As String
    Public Property Bar() As String
        Get
            Return m_Bar
        End Get
        Set(value As String)
            m_Bar = Value
        End Set
    End Property
    Private m_Bar As String
End Class

Public Class Group
    Public Sub New()
        Me.Members = New List(Of String)()
    End Sub

    Public Property ID() As Integer
        Get
            Return m_Id
        End Get
        Set(value As Integer)
            m_Id = value
        End Set
    End Property
    Private m_Id As String
    Public Property Name() As String
        Get
            Return m_Name
        End Get
        Set(value As String)
            m_Name = Value
        End Set
    End Property
    Private m_Name As String
    Public Property Members() As List(Of String)
        Get
            Return m_Members
        End Get
        Set(value As List(Of String))
            m_Members = Value
        End Set
    End Property
    Private m_Members As List(Of String)
End Class
Imports QBI
Imports QBI.QBI
Imports QBI.AppCore.Xutilities

Public Class TestDGV1

    Public dgv1 As DataGridView

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

        Dim ordlineitems As List(Of OrderLineItemICT)
        ordlineitems = Order_DataICT.GetNewOrderLineItemsICT("26073bff-3a08-4bc2-8da9-79c75534bd6b")
        dgv1 = Me.CreateDGV(ordlineitems) 'create the DataGridView and save it as "dgv1" (which must be publically accessible)

        Me.SplitContainer1.Panel2.Controls.Add(dgv1) 'NOTE, the datagridview is inside a SplitContainer
    End Sub

    Public Function CreateDGV(dsItems As List(Of OrderLineItemICT)) As DataGridView
        Dim dgv As New DataGridView()
        dgv.Dock = DockStyle.Fill
        dgv.DataSource = dsItems
        dgv.EditMode = DataGridViewEditMode.EditOnEnter
        dgv.AutoGenerateColumns = False
        dgv.AllowUserToAddRows = False

        Dim L As New QBI.OrderLineItemICT 'only using this reference for my column names defined elsewhere

        Dim col0 As New DataGridViewComboBoxColumn With {.Name = "Match", .DataPropertyName = "NameMatch", .DisplayMember = "Name", .ValueMember = "ListID", .HeaderText = "Matches", .AutoComplete = True}
        col0.DisplayIndex = 0

        Dim col1 As New DataGridViewTextBoxColumn With {.Name = L.col_LineItemBvin, .DataPropertyName = L.col_LineItemBvin, .Visible = False, .ReadOnly = True, .HeaderText = L.col_LineItemBvin}
        col1.DisplayIndex = 1

        Dim col2 As New DataGridViewTextBoxColumn With {.Name = L.col_ProductId, .DataPropertyName = L.col_ProductId, .Visible = False, .ReadOnly = True, .HeaderText = L.col_ProductId}
        col2.DisplayIndex = 2

        Dim col3 As New DataGridViewTextBoxColumn With {.Name = L.col_ProductSku, .DataPropertyName = L.col_ProductSku, .Visible = True, .ReadOnly = True, .HeaderText = "SKU"}
        col3.DisplayIndex = 3
        col3.Width = 160
        Dim col4 As New DataGridViewTextBoxColumn With {.Name = L.col_Quantity, .DataPropertyName = L.col_Quantity, .Visible = True, .ReadOnly = True, .HeaderText = "QTY"}
        col4.DisplayIndex = 9
        col4.Width = 65
        col4.DefaultCellStyle.Format = "n0"
        col4.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter

        Dim col5 As New DataGridViewTextBoxColumn With {.Name = L.col_BasePrice, .DataPropertyName = L.col_BasePrice, .Visible = True, .ReadOnly = True, .HeaderText = "Base Price"}
        col5.DisplayIndex = 6
        col5.DefaultCellStyle.Format = "c2"
        col5.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
        col5.Width = 85

        Dim col6 As New DataGridViewTextBoxColumn With {.Name = L.col_Discounts, .DataPropertyName = L.col_Discounts, .Visible = True, .ReadOnly = True, .HeaderText = "Discounts"}
        col6.DisplayIndex = 7
        col6.DefaultCellStyle.Format = "c2"
        col6.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
        col6.Width = 80

        Dim col7 As New DataGridViewTextBoxColumn With {.Name = L.col_AdjustedPrice, .DataPropertyName = L.col_AdjustedPrice, .Visible = True, .ReadOnly = True, .HeaderText = "Adj Price"}
        col7.DisplayIndex = 8
        col7.DefaultCellStyle.Format = "c2"
        col7.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
        col7.Width = 80

        Dim col8 As New DataGridViewTextBoxColumn With {.Name = L.col_LineTotal, .DataPropertyName = L.col_LineTotal, .Visible = True, .ReadOnly = True, .HeaderText = "Line Total"}
        col8.DisplayIndex = 11
        col8.DefaultCellStyle.Format = "c2"
        col8.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
        col8.Width = 80

        Dim col9 As New DataGridViewTextBoxColumn With {.Name = L.col_ProductName, .DataPropertyName = L.col_ProductName, .Visible = True, .ReadOnly = True, .HeaderText = "Product Name"}
        col9.DisplayIndex = 4
        col9.Width = 170

        Dim col10 As New DataGridViewTextBoxColumn With {.Name = L.col_ProductShortDescription, .DataPropertyName = L.col_ProductShortDescription, .Visible = False, .ReadOnly = True, .HeaderText = L.col_ProductShortDescription}
        col10.DisplayIndex = 5

        Dim col11 As New DataGridViewTextBoxColumn With {.Name = L.col_ShippingWeight, .DataPropertyName = L.col_ShippingWeight, .Visible = True, .ReadOnly = True, .HeaderText = "Unit Wt"}
        col11.DisplayIndex = 12
        col11.DefaultCellStyle.Format = "N1"
        col11.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
        col11.Width = 70
        Dim col12 As New DataGridViewTextBoxColumn With {.Name = L.col_ShippingWidth, .DataPropertyName = L.col_ShippingWidth, .Visible = False, .ReadOnly = True, .HeaderText = L.col_ShippingWidth}
        col12.DisplayIndex = 13

        Dim col13 As New DataGridViewTextBoxColumn With {.Name = L.col_ShippingHeight, .DataPropertyName = L.col_ShippingHeight, .Visible = False, .ReadOnly = True, .HeaderText = L.col_ShippingHeight}
        col13.DisplayIndex = 14

        Dim col14 As New DataGridViewTextBoxColumn With {.Name = L.col_ShippingBoxCount, .DataPropertyName = L.col_ShippingBoxCount, .Visible = False, .ReadOnly = True, .HeaderText = L.col_ShippingBoxCount}
        col14.DisplayIndex = 15

        Dim col15 As New DataGridViewTextBoxColumn With {.Name = L.col_CustomProperties, .DataPropertyName = L.col_CustomProperties, .Visible = False, .ReadOnly = True, .HeaderText = L.col_CustomProperties}
        col15.DisplayIndex = 16

        Dim col16 As New DataGridViewTextBoxColumn With {.Name = L.col_UOM, .DataPropertyName = L.col_UOM, .Visible = True, .ReadOnly = True, .HeaderText = "Units"}
        col16.DisplayIndex = 10
        col16.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
        col16.Width = 55

        dgv.Columns.AddRange({col0, col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11, col12, col13, col14, col15, col16})

        AddHandler dgv.DataBindingComplete, AddressOf dgvLineItems_DataBindingComplete

        Return dgv
    End Function

    Private Sub dgvLineItems_DataBindingComplete(sender As Object, e As DataGridViewBindingCompleteEventArgs)
        For Each row As DataGridViewRow In Me.dgv1.Rows
            Dim dr = DirectCast(row.DataBoundItem, OrderLineItemICT)
            If dr Is Nothing Then
                Return
            End If

            Dim name As String = row.Cells(dr.col_ProductName).Value.ToString
            Dim SKU As String = row.Cells(dr.col_ProductSku).Value.ToString
            Dim cell As DataGridViewComboBoxCell = DirectCast(row.Cells("Match"), DataGridViewComboBoxCell)
            Dim wpm_items As List(Of WPM_Item) = GetComboboxData(name, SKU) 'function inside
            If cell.DataSource Is Nothing Then
                cell.DataSource = wpm_items 
                cell.DisplayMember = "Name"
                cell.ValueMember = "ListID"
                cell.Value = cell.Items(0).ListID
            End If
        Next
    End Sub

    Public Function GetComboboxData(ProductNameToMatch As String, ProductSKUToMatch As String) As List(Of WPM_Item)
        'this function returns a list of returned matches for a given row's ProductName or SKU
        'this function will be the datasource for a given combobox
        Dim itms As New List(Of WPM_Item)
        itms = WPM_Data.FindWPM_ItemMatch(ProductNameToMatch, ProductSKUToMatch)
        Return itms
    End Function

End Class