【问题标题】:Filter a DataGridView without losing unbound changes过滤 DataGridView 而不会丢失未绑定的更改
【发布时间】:2016-07-09 13:27:46
【问题描述】:

我正在开发一个 vb.net 应用程序,并且我有一个显示员工列表的 dgv。 dgv 有一个未绑定的复选框列,用于为所需操作选择员工。我使用 rowFilter 按部门或位置或用户选择的任何内容过滤列表。

如果用户使用部门 1 过滤并选中他想要的员工旁边的复选框,选择他们,然后过滤到部门 2,选择更多员工,当我们过滤回部门 1 时,选中的员工是不再检查了。

我怎样才能做到这样,一旦检查了员工,您就可以使用其他参数进行过滤,而不会丢失之前的选择。我正在考虑在下一个过滤器之前将每个员工的检查状态保存到数据库中,但我觉得可能是一种更快更简单的方法。有吗?

这是我用来填充 dgv 的代码

 sql = "SELECT employee_paysetup.EmployeeNumber AS EmployeeNo, employee_paysetup.FName, employee_paysetup.MName, " _
                & "employee_paysetup.LName, (case when employee_paysetup.MName = ' ' then concat(employee_paysetup.FName,' ' , employee_paysetup.LName) else " _
                & "concat(employee_paysetup.FName,' ' , employee_paysetup.MName,' ' , employee_paysetup.LName) end) " _
                & "AS FullName, costcenters.CostCenterName AS cosName, departments.DepartmentName AS depName, " _
                & "positions.PositionName AS posName, locations.LocationName AS locName, CostCenter, Department, Position, EmployeeLocation, PayGroup " _
                & "FROM ((((((employee_paysetup LEFT JOIN employees ON employee_paysetup.EmployeeNumber = employees.EmployeeNumber) " _
                & "LEFT JOIN costcenters ON employees.CostCenter = costcenters.CostCenterID) " _
                & "LEFT JOIN departments ON employees.Department = departments.DepartmentID) " _
                & "LEFT JOIN positions ON employees.Position = positions.PositionID) " _
                & "LEFT JOIN locations ON employees.EmployeeLocation = locations.LocationID) " _
                & "LEFT JOIN paygroups ON employee_paysetup.PayGroup = paygroups.ID) " & filterValue
        cmd = New MySqlCommand(sql, conn)
        cmd.Parameters.AddWithValue("@Status", "ACTIVE")
        da.SelectCommand = cmd
        dt.Clear()
        da.Fill(dt)
        'sort
        dt.DefaultView.Sort = "FullName ASC"
        dgvEmployees.DataSource = dt.DefaultView

我过滤使用

dt.DefaultView.RowFilter  = "myFilter"

【问题讨论】:

  • 将员工转换为“视图模型”并添加选定的属性以便您可以绑定它。
  • Crowcoder 能否详细说明一下
  • 你应该edit你的帖子添加一些代码来显示你在做什么以及如何做。我们不知道一个细节。

标签: .net vb.net datagridview


【解决方案1】:

问题是我们没有为未绑定的列提供存储。一个相当简单的方法是使用DataTable。通过 SQL 添加一个Selected 列,以便在DataTable 中为其创建一个列:

Dim sql = "SELECT False As Selected, Id, Name, Descr, Bird, Color, ItemDate FROM Sample"

对于大多数数据库提供程序,这将正常工作:该表将有一个布尔列,而 DGV 将为它添加一个检查列。但是 MySQL 存在一个小问题,因为它缺少将 CAST 转换为 Boolean 或 tinyint 的方法。因此,该列将是文本。因此,对于 MySql,跳过 SQL Selected 列并在表中添加一个新列:

' after the DS is built, but BEFORE it is bound to the DGV:
Dim dc As New DataColumn("Selected", GetType(Boolean))
dc.DefaultValue = False    ' important!
dtSample.Columns.Add(dc)
dc.SetOrdinal(0)           ' make it column 0

请务必将DefaultValue 设置为某个值,否则所有行都将设置为DBNull 并阻塞检查列。在构建DataSource/DataTable将其绑定到 DGV 之前 执行此操作也很重要。

您还可以在 ColumnAdded 事件中捕获并替换 Check 列的 Text 列。无论哪种方式 NET 都知道它是一个“虚拟”列,因此它不会干扰您可能为 DataAdapter 构建的任何 DBCommand 对象(OP 不能基于该查询获得任何对象,但未来的读者可能会)。结果:

我检查选择了几个 orangeStork 行,然后过滤并保留检查。在核心上,这和 CrowCoder 先生的回答做同样的事情只是不同:提供存储Selected 状态的地方。该方法利用DGV的正常能力自动保存到DataTable


如果你想使用ColumnAdded事件:

If e.Column.Name = "Selected" AndAlso TypeOf e.Column Is DataGridViewTextBoxColumn Then
    Dim dc As New DataGridViewCheckBoxColumn()
    dc.HeaderText = "Selected"
    dc.Name = "Selected"
    dc.DataPropertyName = "Selected"
    dc.ValueType = GetType(Boolean)
    dgv5.Columns.Remove(e.Column)
    dgv5.Columns.Insert(0, dc)
    dc.DisplayIndex = 0
End If

真正重要的事情是分配DataPropertyName,以便 DGV 知道在表中存储数据的位置。

直接向DataTable添加一列更简单直接,这在其他情况下可能很有用。

【讨论】:

    【解决方案2】:

    假设您有员工:

    Public Class Employee
        Public Property EmpName As String
        Public Property EmpNumber As Integer
    End Class
    

    而且你的 winform 可能有一个获取员工列表的方法:

    Public Function GetEmployees() As List(Of Employee)
            'obviously, actually fill a list...
            Return New List(Of Employee)()
    End Function
    

    通常“视图”(在您的情况下是 winform)与后端数据有不同的需求。所以你做一个EmployeeViewModel

    Public Class EmployeeVM
        Public Property EmpName As String
        Public Property EmpNumber As Integer
        Public Property EmpIsSelected As Boolean
    End Class
    

    因此,您编辑GetEmployees 以获取员工列表并将其转换为EmployeeVM 列表,并将其绑定到网格。然后你可以过滤所有你想要的,EmpIsSelected 属性将持续存在。

    当你 Save 或其他什么时,你将视图模型转换回 Employee

    这是一个基本的 MVVM 模式,解决了 UI 与后端的数据需求不同的问题。

    【讨论】:

    • 太棒了。我会试试的。谢谢!
    猜你喜欢
    • 2014-05-24
    • 1970-01-01
    • 2016-11-01
    • 2016-02-07
    • 2018-11-14
    • 2015-07-07
    • 2015-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多