【问题标题】:Is there a better way to filter this datagridview?有没有更好的方法来过滤这个datagridview?
【发布时间】:2012-06-14 22:40:15
【问题描述】:

我有一个使用 switch 语句通过双击事件过滤的 datagridview。数据源最初是由基于用户输入的 LINQ to SQL 查询设置的,然后他们可以选择双击单元格来过滤模型、计算机名称或操作系统等类似项目。

这里似乎有太多重复的代码。对更好的方法有什么想法吗?

private void gridInventory_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
        try
        {
            if (e.ColumnIndex > 0 && e.RowIndex > 0)
            {
                var cell = this.gridInventory[e.ColumnIndex, e.RowIndex];
                var clickedValue = (cell.Value != null) ? cell.Value.ToString() : string.Empty;

                if (!string.IsNullOrEmpty(clickedValue))
                {
                    switch (this.gridInventory.Columns[e.ColumnIndex].Name.ToUpper())
                    {
                        case @"MODEL":
                            CurrentList = CurrentList.Where(r => r.Model != null && r.Model.ToUpper() == clickedValue.ToUpper()).ToList();
                            break;
                        case @"COMPUTERNAME":
                            CurrentList = CurrentList.Where(r => r.ComputerName != null && r.ComputerName.ToUpper() == clickedValue.ToUpper()).ToList();
                            break;
                        case @"SERIALNUMBER":
                            CurrentList = CurrentList.Where(r => r.SerialNumber != null && r.SerialNumber.ToUpper() == clickedValue.ToUpper()).ToList();
                            break;
                        case @"COMPUTERID":
                            CurrentList = CurrentList.Where(r => r.ComputerID.ToString().ToUpper() == clickedValue.ToUpper()).ToList();
                            break;
                        case @"MANUFACTURER":
                            CurrentList = CurrentList.Where(r => r.Manufacturer != null && r.Manufacturer.ToUpper() == clickedValue.ToUpper()).ToList();
                            break;
                        case @"OSVERSION":
                            CurrentList = CurrentList.Where(r => r.OSVersion != null && r.OSVersion.ToUpper() == clickedValue.ToUpper()).ToList();
                            break;
                        case @"AUDITDATE":
                            CurrentList = CurrentList.Where(r => r.AuditDate != null && r.AuditDate.ToString().ToUpper() == clickedValue.ToUpper()).ToList();
                            break;
                        case @"AUDITGUID":
                            CurrentList = CurrentList.Where(r => r.AuditGUID != null && r.AuditGUID.ToString().ToUpper() == clickedValue.ToUpper()).ToList();
                            break;
                        default:
                            break;
                    }

                    if (this.CurrentList != null)
                    {
                        gridInventory.DataSource = this.CurrentList;
                        this.lblRecords.Text = string.Format(@"Total Records: {0}", CurrentList.Count(c => c.ComputerID > 0));
                    }
                }
            }
        }
        catch (Exception exc)
        {
            MessageBox.Show(exc.Message, @"error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

【问题讨论】:

    标签: c# datagridview code-cleanup


    【解决方案1】:

    使用 LINQ 和反射,这个函数可以这样重写:

    private void gridInventory_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
    {
            try
            {
                if (e.ColumnIndex > 0 && e.RowIndex > 0)
                {
                    var cell = this.gridInventory[e.ColumnIndex, e.RowIndex];
                    var clickedValue = (cell.Value != null) ? cell.Value.ToString() : string.Empty;
                    if (!string.IsNullOrEmpty(clickedValue))
                    {
                        CurrentList = CurrentList.Where(r => typeof(r_type_here).GetProperty(this.gridInventory.Columns[e.ColumnIndex].Name).GetValue(r, null) != null &&
                            typeof(r_type_here).GetProperty(this.gridInventory.Columns[e.ColumnIndex].Name).GetValue(r, null).ToString().ToUpper() == clickedValue.ToUpper()).ToList();
    
                        if (this.CurrentList != null)
                        {
                            gridInventory.DataSource = this.CurrentList;
                            this.lblRecords.Text = string.Format(@"Total Records: {0}", CurrentList.Count(c => c.ComputerID > 0));
                        }
                    }
                }
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message, @"error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    

    r_type_here 替换为CurrentList 中的实际元素类型,您应该会得到相同的结果。

    优点:

    • 代码更短
    • 代码更灵活 - 如果您想添加新的 column/property 那么你就不需要写一行代码了 这里

    缺点:

    • 您必须保持字符大小写 - 即列表元素类的属性名称中的大小写应该与 gridInventory.Columns 中相应列的名称具有完全相同的大小写
    • 可读性较差的代码
    • 如果您频繁使用此函数,可能会成为性能瓶颈 - 反射通常比您的案例语句慢。

    还应在同一个 LINQ where 语句中实现对属性存在性的检查。

    【讨论】:

    • 谢谢!这很好用。我喜欢这段代码提供的灵活性,因为我们将来很可能会添加列。至于案例问题,属性名称和列名称都来自同一个数据源,所以这不应该是一个问题。再次感谢您。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-15
    • 2013-08-18
    相关资源
    最近更新 更多