1

在 VBS 2015 中,我创建了一个表单,该表单使用 LINQ 查询来导入名称、位置、年龄等的 CSV 文件,并使用唯一记录进行排序。数据被输入到数据网格中,然后可以通过从 MenuStrip 中选择按钮进行过滤和排序。使用 LINQ 查询进行排序和过滤的过程非常简单;数组可以按升序或降序排序,也可以按字段之一排序。如果该字段与查询匹配,则整个记录(五个字段)将显示在数据网格中。

到目前为止一切都很好,但这是我的问题:

如何在不为每个条件组合编写完整查询的情况下同时应用两个不同的条件?

例如,为了明确我的问题,我可以使用原始查询按降序对数组进行排序,但是当我选择过滤器时,结果会按升序显示。反之亦然,如果结果已经使用五个字段可能性之一进行过滤,我如何将排序按钮应用于预过滤结果?

通过为每个过滤器/排序组合编写单独的查询,我想出了一个非常冗长和复杂的方法。每次选择一个按钮时,都会使用基于 mnuButton.Checked = True/False 布尔值的 If 块评估另一个菜单的检查值,然后运行并显示相应的查询。

这是我在按下某个过滤器按钮时执行的代码的示例。这个 sub 应该检查是否已经选择了一个排序按钮,然后,基于此,运行返回相同过滤结果的两个查询之一,只是按升序或降序排列。

Private Sub mnuFilterEurope_Click(sender As Object, e As EventArgs) Handles mnuFilterEurope.Click

Dim memberinfo() As String = File.ReadAllLines("easterndiv_mission.txt")
Dim n = memberinfo.Count - 1
ReDim Missionaries(n) 'this is based on a structure defined outside this sub
Dim line As String
Dim data(5) As String
For i As Integer = 0 To n
  line = memberinfo(i)
  data = line.Split(","c)
  Missionaries(i).Last = data(0)
  Missionaries(i).First = data(1)
  Missionaries(i).State = data(2)
  Missionaries(i).Age = CInt(data(3))
  Missionaries(i).ServiceYears = CInt(data(4))
  Missionaries(i).Location = data(5) 'this is the field the 'filter' query will be evaluating.
Next
'if the 'ascending' button is selected, format the results in ascending order
If mnuSortAscending.Selected = True Then
  checkEurope() ' this references a sub procedure that selects the pressed button and deselects the other four in the menu.
  Dim populationQuery = From entry In Missionaries
                        Where entry.Location = "Europe"
                        Order By entry.Last
                        Select entry.Last, entry.First, entry.State, entry.Age, entry.ServiceYears, entry.Location
  If populationQuery.Count() > 0 Then 'check that results will be returned
    dgvOutput.DataSource = populationQuery.ToList
    dgvOutput.CurrentCell = Nothing
  Else
    MessageBox.Show("No results found")
    Exit Sub
  End If
Else
  'if the 'descending' button is selected, format the results in descending order
  checkEurope()
  Dim populationQuery = From entry In Missionaries
                        Where entry.Location = "Europe"
                        Order By entry.Last Descending
                        Select entry.Last, entry.First, entry.State, entry.Age, entry.ServiceYears, entry.Location
  If populationQuery.Count() > 0 Then
    dgvOutput.DataSource = populationQuery.ToList
    dgvOutput.CurrentCell = Nothing
  End If
End If
End Sub

这对于一个按钮来说是极其漫长、笨拙和耗时的,并且有十种不同的可能性......?我确信有更好的方法来编写可重用查询或仅对数据网格中显示的结果进行排序......而不是从原始文件中提取的内容。

由于用于对查询结果进行排序的菜单项非常常见,因此我确信这里有一种简化的方法可以实现我的最终目标。

在此先感谢您的帮助,对于任何不清楚和这个问题的不公平之处,我提前道歉......我只使用 VB 几个星期。

4

1 回答 1

0

您的目标是在If mnuSortAscending.Selected分支中没有与应用Order By entry.LastOrder By entry.Last Descending. 正如您所说,这是保持代码可维护性的必要目标。所以任务是把每一个被复制的东西移动到一个地方,无论是之前还是之后If

checkEurope() ' this references a sub procedure that selects the pressed button and deselects the other four in the menu.
Dim populationQuery = From entry In Missionaries
                      Where entry.Location = "Europe"

'if the 'ascending' button is selected, format the results in ascending order
If mnuSortAscending.Selected = True Then
   populationQuery = From entry In populationQuery
                     Order By entry.Last
Else
   populationQuery = From entry In populationQuery
                     Order By entry.Last Descending
End If

populationQuery = From entry In populationQuery
                  Select entry.Last, entry.First, entry.State, entry.Age, entry.ServiceYears, entry.Location

If populationQuery.Count() > 0 Then 'check that results will be returned
  dgvOutput.DataSource = populationQuery.ToList
  dgvOutput.CurrentCell = Nothing
Else
  MessageBox.Show("No results found")
  Exit Sub
End If

这有帮助吗?

如果你想更简洁,= Trueis 一个空操作(在已经是布尔值的东西上),所以你可以把它排除在外。此外,LINQ 只是常规 VB 方法调用的语法糖。From entry In populationQuery Order By entry.Last与 相同populationQuery.OrderBy(Function (entry) entry.Last)

If mnuSortAscending.Selected Then
   populationQuery = populationQuery.OrderBy(Function (entry) entry.Last)
Else
   populationQuery = populationQuery.OrderByDescending(Function (entry) entry.Last)
End If

If最后,您可以通过将其从语句形式转换为表达式形式(三元运算符)来将重复减少到更进一步的极端,对进行重复数据删除populationQuery =

populationQuery = If(mnuSortAscending.Selected,
    populationQuery.OrderBy(Function (entry) entry.Last),
    populationQuery.OrderByDescending(Function (entry) entry.Last))
于 2017-10-02T19:51:07.430 回答