0

Так что я время от времени работаю в Winforms в устаревшем приложении и не всегда знаком с лучшими практиками во всех случаях с привязанными объектами. В принципе, у меня есть три части, в которых у меня два человека, у них может быть только один продукт, но этот продукт может привести к тому, что у него будут разные наборы SKU. Есть ли способ инициировать событие и совокупность выпадающих списков из значений первого со списком? Я искал вокруг, и я либо нахожу основные данные о том, как связать combobox (я могу это сделать), либо сделать что-то с тем, как вы его связываете. Не привязывается после активации зависимого родительского изменения и изменения набора данных. Пример ниже:DataGridView Cascading/Dependent ComboBox Columns

Pocos:

Public Class Person 
    Public Property PersonID As Integer 
    Public Property FirstName As String 
    Public Property LastName As String 
    Public Property ProductId As Integer 
    Public Property SkuId As Integer 
End Class 

Public Class Product 
    Public Property ProductId As Integer 
    Public Property Description As String 
End Class 

Public Class Sku 
    Public Property SKUId As Integer 
    Public Property ProductId As Integer 
    Public Property Description As String 
End Class 

Главный пример кода (базовый интерфейс действительно только имеет Datset маркирован «дц», который соответствует почти тождественна личности и продукт Pocos с DataTables A DataGridView «DGV», столбцы. связаны с данными в Person КРОМЕ колонке под названием SKU та не имеет никакой привязки, как я хочу, чтобы связать это после того, как тот факт, что и где я терпеть неудачу. в

Update 9-13-2016 я могу получить приведенный ниже код для работы ЗА ИСКЛЮЧЕНИЕМ в некоторых крупномасштабных решениях (вся причина, по которой я это сделал). Он в основном НЕ выполнит линию, которая передает ячейку() в datagridviewcomboboxcell и игнорирует ее и перескакивает через линию. Нет причин, он просто перепрыгивает через него. Мне интересно, если на больших классах представления datagrid могут стать коррумпированными или чем-то еще.

Основной код:

Private _people As List(Of Person) = New List(Of Person) 
Private _products As List(Of Product) = New List(Of Product) 
Private _SKUs As List(Of Sku) = New List(Of Sku) 
Private _initialLoadDone = False 
Private _currentRow As Integer? = Nothing 

Private Sub DynamicComboBoxDoubleFill_Load(sender As Object, e As EventArgs) Handles MyBase.Load 
    _products = New List(Of Product)({ 
            New Product With {.ProductId = 1, .Description = "Offline"}, 
            New Product With {.ProductId = 2, .Description = "Online"} 
            }) 

    Dim s = "" 
    For Each o In _products 
     Dim row As DataRow = ds.Tables("tProducts").NewRow 
     row("ProductId") = o.ProductId 
     row("Description") = o.Description 
     ds.Tables("tProducts").Rows.Add(row) 
    Next 

    _SKUs = New List(Of Sku)({ 
    New Sku With {.SKUId = 1, .ProductId = 1, .Description = "Mail"}, 
    New Sku With {.SKUId = 2, .ProductId = 1, .Description = "Magazine"}, 
    New Sku With {.SKUId = 3, .ProductId = 2, .Description = "Email"}, 
    New Sku With {.SKUId = 4, .ProductId = 2, .Description = "APIRequest"} 
    }) 

    Dim items = _SKUs 

    _people = New List(Of Person)({ 
     New Person With {.PersonID = 1, .FirstName = "Emily", .LastName = "X", .ProductId = 1, .SkuId = 1}, 
     New Person With {.PersonID = 2, .FirstName = "Brett", .LastName = "X", .ProductId = 2, .SkuId = 3} 
            }) 
    For Each p In _people 
     Dim row As DataRow = ds.Tables("tPeople").NewRow 
     row("PersonId") = p.PersonId 
     row("FirstName") = p.FirstName 
     row("LastName") = p.LastName 
     row("ProductId") = p.ProductId 
     row("SkuId") = p.SkuId 
     ds.Tables("tPeople").Rows.Add(row) 
    Next 

    For Each row As DataGridViewRow In dgv.Rows 
     ArrangeValuesForSKUComboBox(row) 
    Next 

    _initialLoadDone = True 
    End Sub 

    Private Sub ArrangeValuesForSKUComboBox(row As DataGridViewRow) 
    Dim productId = CInt(row.Cells("ProductId")?.Value) 
    Dim skus = _SKUs.Where(Function(x) x.ProductId = productId).ToList().Select(Function(x) New With {Key .SkuId = x.SKUId, .SkuDesc = x.Description}).ToList() 

    Dim cell = row.Cells("SKU") 
    'Yeah I don't always work. In this example I do, in others I won't. 
    'For this reason I just want more ideas. I don't care if you completely blow up how the binding is done and do something else entirely. 
    Dim combobox = CType(cell, DataGridViewComboBoxCell) 
    combobox.DataSource = skus 
    combobox.ValueMember = "SKUId" 
    combobox.DisplayMember = "SkuDesc" 
    combobox.Value = skus.FirstOrDefault()?.SkuId 
    End Sub 

    Private Sub dgv_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles dgv.CellValueChanged 
    If _initialLoadDone Then 
     Dim headerText As String = TryCast(sender, DataGridView).Columns(e.ColumnIndex).HeaderText 
     If headerText = "PRODUCT" Then 
     ArrangeValuesForSKUComboBox(dgv?.CurrentRow) 
     End If 
    End If 
    End Sub 
+0

Не могли бы вы дать databased пример того, что вы после этого? Похоже, вы хотите, чтобы содержимое одного источника данных cbo изменилось в зависимости от выбора в другом столбце **, но ** вы пробиваете все строки, которые звучат так, будто они не меняются? – Plutonix

+0

Это действительно изменение пользовательского интерфейса, которое я предоставляю пользователю, а не изменение базы данных. В приведенном выше примере это меняется, проблема заключается в гораздо большем решении, и это не сработает. Я не знаю, почему это не сработает, поэтому я надеялся, что кто-то сможет дать подобную ситуацию, и как они сделали это по-другому, и я мог бы это сделать. Кроме того, мне может потребоваться перестроить класс 1000+ с нуля. Данные в решении в основном являются основным набором, A, приводит к фиксированному выбору 1 или 2 в наборе B, который затем будет динамически изменять C, чтобы быть 1 или 2 для выбора 1 из B, или 3 или 4 для выбора 2 из B. – djangojazz

+0

Под «databased» я хотел показать нам, что вы хотите, используя некоторые простые данные образца. Я вижу содержимое трех списков, но единственный способ «увидеть это изменение» - это иметь БД с базовой таблицей, что, конечно же, мы ничего не знаем. Я * думаю * Я сделал это, но мне трудно понять правила (я читал эту 4 раза пре-баунти) – Plutonix

ответ

2

Чтобы иметь зависимую (каскадное или ведущий/ведомый) ComboBox столбцы в DataGridView, вы можете следовать этим шагам:

  1. Установить DataSource рабского колонке все имеющиеся значения.

    Цель: Здесь цель предотвратить ошибки рендеринга при первой загрузке, так что все подчиненные комбинированные окна могут показывать правильное значение.

  2. Hanlde EditingControlShowing событие сетки и проверить, если текущая ячейка является ведомым комбо клетки, а затем получить контроль редактирования с использованием e.Control, который имеет тип DataGridViewComboBoxEditingControl. Затем проверьте значение главной комбинированной ячейки и установите свойство управления редактированием DataSource подходящему подмножеству значений на основе значения главной комбинированной ячейки. Если значение главной ячейки равно NULL, установите источник данных равным null.

    Цель: Здесь цель настройки источника данных ведомого комбо, чтобы показать только подходящие значения при выборе значения из ведомого комбо.

  3. Ручка CellValueChanged и проверьте, является ли текущая ячейка главной комбо, а затем установите для зависимой ячейки значение null.
    Примечание: Вместо того, чтобы значение ведомой ячейки было равно нулю, вы можете установить его для первого доступного допустимого значения на основе значения основной ячейки.

    Цель: Здесь цель предотвратить ведомое комбо иметь недопустимые значения после того, как значение главного комбо изменилось, поэтому мы сбрасываем значение.

В соответствии с приведенными выше правилами вы можете иметь столько зависимых полетов, сколько вам нужно.

Пример

В приведенном ниже примере у меня есть таблица Country (Id, Name), таблицы состояний (Id, Name, CountryId) и таблицы популяции (CountryId, StateId, население). И я хочу выполнить ввод данных для таблицы Population, используя 2 столбца со списком для страны и штата и текстовый столбец для населения. Я знаю, что это не обычный дизайн БД, но это только для примера наличия/ведомого (зависимые) столбцы поля со списком основных в сетке:

Private Sub EditingControlShowing(sender As Object, _ 
    e As DataGridViewEditingControlShowingEventArgs) _ 
    Handles PopulationDataGridView.EditingControlShowing 

    Dim grid = DirectCast(sender, DataGridView) 
    If (grid.CurrentCell.ColumnIndex = 1) Then 'State column 
     Dim combo = DirectCast(e.Control, DataGridViewComboBoxEditingControl) 
     If (grid.CurrentRow.Cells(0).Value IsNot DBNull.Value) Then 
      Dim data = Me.DataSet1.State.AsDataView() 
      data.RowFilter = "CountryId = " + grid.CurrentRow.Cells(0).Value.ToString() 
      combo.DataSource = data 
     Else 
      combo.DataSource = Nothing 
     End If 
    End If 
End Sub 

Private Sub CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) _ 
    Handles PopulationDataGridView.CellValueChanged 
    Dim grid = DirectCast(sender, DataGridView) 
    If (e.ColumnIndex = 0 And e.RowIndex >= 0) Then 'Country Column 
     grid.Rows(e.RowIndex).Cells(1).Value = DBNull.Value 'State Column 
    End If 
End Sub 
+0

Решение не зависит от 'DataTable' или любой другой структуры данных. Пример - это просто пример, который использует 'DataTable'. Вы можете просто использовать свои собственные классы POCO и любое другое хранилище, которое у вас есть. Дайте мне знать, если вам нужно какое-либо разъяснение или у вас есть какие-либо вопросы по поводу ответа :) –

+0

Мне нравится ваш метод лучше, чем у меня, спасибо. Пример вашего фильтра кажется немного неправильным, поскольку, как представляется, эта часть: «Dim data = ds.Tables (« State »). AsDataView() data.RowFilter =" CountryId = "+ grid.CurrentRow.Cells (0) .Value .ToString() combo.DataSource = data ' – djangojazz

+0

Может быть: Dim dvStates = Новый DataView (ds.Tables ("State"), $ "CountryId =' {grid.CurrentRow.Cells (0) .Value} '", «Id ASC», DataViewRowState.CurrentRows) combo.DataSource = dvStates combo.ValueMember = "Id" combo.DisplayMember = "Имя". Я думаю, вы должны сказать combobox «ValueMember» и «DisplayMember», или просто думает, что это datagridviewrow в противном случае. – djangojazz

Смежные вопросы