2016-05-26 2 views
1

Происходит: У меня есть таблица, состоящая из Name, ID, Comments. Каждый идентификатор уникален, если пользователь не отправляет более 1 записи. В тот момент, когда пользователь может иметь 3 строки, где идентификатор один и тот же, чтобы показать эти записи, все они были введены одним пользователем, и они принадлежат друг другу.Групповые записи данных по значению строки после разделения

Ниже я опубликую то, что я сделал первоначально, чтобы разделить их на отдельные datagridview с кнопками ниже каждого, которые в конечном итоге будут использоваться для работы с записями данных над ним.

Таким образом, это приводит к двум вещам, которые я пытаюсь выяснить, и не испытал большой удачи в ходе проб и ошибок и исследования Google.

1.) Как я могу сделать это помещать любые записи в datatable, которые имеют один и тот же идентификатор в один и тот же файл datagridview, а не создавать отдельный datagrid для каждого из них.

2.) Предполагая, что вышесказанное может быть сделано, как я мог бы, если это возможно, сделать, чтобы кнопка, образующая под каждым, соответствовала только таблице данных над ней? Могут ли каждый datagrid и кнопка, хотя и созданы программно, назначать уникальный идентификатор, который позволяет каждому соответствовать другому?

Dim dst As New DataSet 
    For i As Integer = 0 To DT.Rows.Count - 1 
     Dim intLastRow As Integer = i 
     If intLastRow > DT.Rows.Count - 1 Then intLastRow = DT.Rows.Count - 1 
     Dim dtbNew As DataTable = DT.Clone 
     dtbNew.TableName = DT.TableName 
     For j As Integer = i To intLastRow 
      dtbNew.ImportRow(DT.Rows(j)) 
     Next j 
     dst.Tables.Add(dtbNew) 
    Next i 

    For Each table As DataTable In dst.Tables 
     Dim DGV As New DataGridView 
     Dim BTN As New Button 
     BTN.Text = "Show Details" 
     BTN.Width = 120 
     DGV.DataSource = table 
     DGV.Width = 800 
     DGV.Height = 80 
     FlowLayoutPanel1.Controls.Add(DGV) 
     FlowLayoutPanel1.Controls.Add(BTN) 
    Next 
    FlowLayoutPanel1.AutoScrollPosition = New Point(FlowLayoutPanel1.Top) 

Ошибки

Dim DT As New DataTable 
    DT.Load(SQLMP) 

    Dim groups As IEnumerable(Of IGrouping(Of Integer, DataRow)) = DT.Select.GroupBy(Function(row) row.Field(Of Integer)("ORDER_ID")) 

Необработанное исключение типа 'System.InvalidCastException' произошло в System.Data.DataSetExtensions.dll`

Дополнительная информация: Указанный литая не действует

+0

Попытка замены 'тусклых группы в IEnumerable (Of IGrouping (целочисленного, DataRow)) = DT.Select.GroupBy (функция (строка) row.Field (Of Integer) ("ORDER_ID")) 'by' Dim groups = DT.Select.GroupBy (строка функции). Поле (Integer) ("ORDER_ID")) '. Какой тип выводится на «группы»? – VBobCat

+0

Подождите минуту :-) какой тип поля ** "ORDER_ID" **? Если это не целое число, а строка или что-то еще, это значит, что Cast не работает ... – VBobCat

+0

Нет целого числа. – Lee

ответ

0

Вы можете делать то, что хотите, с функциями LinQ и лямбда Допустим, вы есть DataTable со всеми этими элементами, смешанными.

Сделайте это, и вы получите строки сгруппированы по ID:

Dim groups = DT.Select.GroupBy(Function(row) row("ID")) 

Теперь вы можете извлечь частичное DataTables из него

Dim partialTables = groups.Select(
    Function(group) 
     Dim partialTable = group.CopyToDataTable 
     partialTable.TableName = group.Key 
     Return partialTable 
    End Function).ToList 

Тогда вы можете запросить список таблиц для конкретного ID, извлеките его и используйте в качестве источника данных:

YourDataGridView.DataSource = partialtables.FirstOrDefault(
    Function(table) table.TableName = "123") 

Надеюсь, это поможет!

EDIT Ниже вы можете увидеть полное воплощение моего предложения. Я проверил это, и это, кажется, работает Ok

Private DT As DataTable, partialTables As List(Of DataTable) 
Private WithEvents CB As ComboBox, DGV As DataGridView 
Private Sub q37459856() 
    DT = New DataTable 
    DT.Columns.Add("Name", GetType(String)) 
    DT.Columns.Add("ID", GetType(Integer)) 
    DT.Columns.Add("Commens", GetType(String)) 
    DT.Rows.Add("aaaaaa", 1, "aaaaaa") 
    DT.Rows.Add("bbbbbb", 2, "bbbbbb") 
    DT.Rows.Add("cccccc", 1, "cccccc") 
    DT.Rows.Add("dddddd", 2, "dddddd") 
    DT.Rows.Add("eeeeee", 3, "eeeeee") 
    DT.Rows.Add("ffffff", 1, "ffffff") 
    DT.Rows.Add("gggggg", 2, "gggggg") 
    DT.Rows.Add("hhhhhh", 3, "hhhhhh") 
    DT.Rows.Add("iiiiii", 4, "iiiiii") 

    Dim groups As IEnumerable(Of IGrouping(Of Integer, DataRow)) = DT.Select.GroupBy(Function(row) row.Field(Of Integer)("ID")) 

    partialTables = groups.Select(
     Function(group) 
      Dim partialTable = group.CopyToDataTable 
      'IGrouping(Of Integer, DataRow) implements IEnumerable(of DataRow) 
      'therefore, it implements Function .CopyToDataTable() 
      partialTable.TableName = group.Key.ToString("000") 
      Return partialTable 
     End Function).ToList 

    Dim IDs = New List(Of String)({"all"}.Concat(partialTables.Select(Function(t) t.TableName))) 

    Dim F As New Form 
    CB = New ComboBox With {.Dock = DockStyle.Top, .DataSource = IDs} 
    F.Controls.Add(CB) 
    DGV = New DataGridView With { 
     .Left = CB.Left, 
     .Top = CB.Top + CB.Height + 3, 
     .Width = CB.Width, 
     .Height = F.ClientSize.Height - CB.Top - CB.Height - 6, 
     .Anchor = AnchorStyles.Left + AnchorStyles.Top + AnchorStyles.Right + AnchorStyles.Bottom, 
     .AllowUserToAddRows = False} 
    F.Controls.Add(DGV) 
    F.Show() 
End Sub 
Sub CB_SelectedValueChanged(sender As Object, e As EventArgs) Handles CB.SelectedValueChanged 
    If CB.SelectedValue = "all" Then 
     DGV.DataSource = DT 
    Else 
     DGV.DataSource = partialTables.FirstOrDefault(Function(t) t.TableName = CB.SelectedValue) 
    End If 
End Sub 

EDIT # 2 Для того, чтобы обеспечить рабочее решение для вопроса, ниже идет версия с подобной логикой, но опираясь на Для ... Далее итераций вместо Linq:

Private DT As DataTable, partialTables As List(Of DataTable) 
Private WithEvents CB As ComboBox, DGV As DataGridView 
Private Sub q37459856_withoutLinq() 
    DT = New DataTable 
    DT.Columns.Add("Name", GetType(String)) 
    DT.Columns.Add("ORDER_ID", GetType(Integer)) 
    DT.Columns.Add("Comments", GetType(String)) 
    DT.Rows.Add("aaaaaa", 1, "aaaaaa") 
    DT.Rows.Add("bbbbbb", 2, "bbbbbb") 
    DT.Rows.Add("cccccc", 1, "cccccc") 
    DT.Rows.Add("dddddd", 2, "dddddd") 
    DT.Rows.Add("eeeeee", 3, "eeeeee") 
    DT.Rows.Add("ffffff", 1, "ffffff") 
    DT.Rows.Add("gggggg", 2, "gggggg") 
    DT.Rows.Add("hhhhhh", 3, "hhhhhh") 
    DT.Rows.Add("iiiiii", 4, "iiiiii") 

    Dim allORDER_ID As New List(Of Integer) 

    For Each dr In DT.Select 
     If Not allORDER_ID.Contains(dr("ORDER_ID")) Then 
      allORDER_ID.Add(dr("ORDER_ID")) 
     End If 
    Next 

    Dim partialTable As DataTable 
    partialTables = New List(Of DataTable) 
    For Each ORDER_ID In allORDER_ID 
     partialTable = DT.Clone 
     partialTable.TableName = ORDER_ID.ToString("000") 
     For Each dr In DT.Select("ORDER_ID=" & ORDER_ID) 
      partialTable.ImportRow(dr) 
     Next 
     partialTables.Add(partialTable) 
    Next 

    Dim IDs = New List(Of String)({"all"}) 

    For Each partialTable In partialTables 
     IDs.Add(partialTable.TableName) 
    Next 

    Dim F As New Form 
    CB = New ComboBox With {.Dock = DockStyle.Top, .DataSource = IDs} 
    F.Controls.Add(CB) 
    DGV = New DataGridView With { 
     .Left = CB.Left, 
     .Top = CB.Top + CB.Height + 3, 
     .Width = CB.Width, 
     .Height = F.ClientSize.Height - CB.Top - CB.Height - 6, 
     .Anchor = AnchorStyles.Left + AnchorStyles.Top + AnchorStyles.Right + AnchorStyles.Bottom, 
     .AllowUserToAddRows = False} 
    F.Controls.Add(DGV) 
    F.Show() 
End Sub 
Sub CB_SelectedValueChanged(sender As Object, e As EventArgs) Handles CB.SelectedValueChanged 
    If CB.SelectedValue = "all" Then 
     DGV.DataSource = DT 
    Else 
     DGV.DataSource = partialTables.FirstOrDefault(Function(t) t.TableName = CB.SelectedValue) 
    End If 
End Sub 
+0

Я думаю, что могу много использовать здесь, и это имеет смысл. Я также должен был добавить, откуда приходит мой первый источник. (выше моего исходного кода) 'Dim DT As New DataTable DT.Load (SQLMP)' (SQLMP - это набор записей sql). Будет ли это по-прежнему применяться здесь, поскольку «GroupBy» не является членом DataRow' – Lee

+0

GroupBy является расширением LinQ и применяется к любому объекту, который реализует IEnumerable (Of T). DT.Select() возвращает массив Datarow, который реализует IEnumerable (Of Datarow), и поэтому может использовать GroupBy и другие функции LinQ. – VBobCat

+0

«CopyToDataTable» не является членом «IGrouping (Of ​​Object, DataRow)». «Раньше я просто не позаботился о моих рекомендациях, я должен был бы это прямо сейчас, если я не пропущу что-то еще. – Lee