C# 如何处理将数据绑定到DataGridView时返回的零行

C# 如何处理将数据绑定到DataGridView时返回的零行,c#,winforms,datagridview,datatable,dataset,C#,Winforms,Datagridview,Datatable,Dataset,我正在用数据库中的数据填充DGV,一切正常,只有0行返回到填充DGV的DataTable时例外。我不确定如何准确地处理这种情况,由于项目要求,我确实需要考虑到这一点 以下是调用数据绑定方法的表单代码: public void PopulateDgvCategories() { string companyFilter = cboSelectCompany.Text; string categoryFilter = cboSelectCategory.Text; db c

我正在用数据库中的数据填充DGV,一切正常,只有0行返回到填充DGV的DataTable时例外。我不确定如何准确地处理这种情况,由于项目要求,我确实需要考虑到这一点

以下是调用数据绑定方法的表单代码:

public void PopulateDgvCategories()
{
    string companyFilter = cboSelectCompany.Text;
    string categoryFilter = cboSelectCategory.Text;

    db categoriesData = new db();

    if (categoryFilter == "All Categories")
    {
        string catsQuery = "SELECT id, category, old_value, old_desc, new_value, new_desc, reference1, reference2 " +
                            "FROM masterfiles.xref WHERE company_name = @company ORDER BY category, old_value";
           this.dtCategories = categoriesData.GetDgvData(catsQuery, companyFilter, categoryFilter);
    }
    else
    {
        string catsQuery = "SELECT id, category, old_value, old_desc, new_value, new_desc, reference1, reference2 " +
                            "FROM masterfiles.xref WHERE company_name = @company and category = @category ORDER BY old_value";
        this.dtCategories = categoriesData.GetDgvData(catsQuery, companyFilter, categoryFilter);
    }

    // Need to check this.dtCategories.Rows.Count
    //  If 0, then need to figure out how to handle that

    dgvCategories.DataSource = this.dtCategories;

    dgvCategories.Columns[0].Visible = false;
    dgvCategories.Rows[0].Cells[0].Selected = false;
}
下面是我如何检索数据并填充数据表:

public DataTable GetDgvData(string selectQuery, string companyFilter, string categoryFilter)
{
    using (NpgsqlConnection conn = new NpgsqlConnection(connString))
    using (NpgsqlCommand cmd = new NpgsqlCommand(selectQuery, conn))
    {
        cmd.Parameters.Add(new NpgsqlParameter("company", companyFilter));
        if (categoryFilter != "All Categories") cmd.Parameters.Add(new NpgsqlParameter("category", categoryFilter));

        DataSet ds = new DataSet();

        conn.Open();

        using (NpgsqlDataAdapter da = new NpgsqlDataAdapter(cmd))
        {
            da.Fill(ds);
        }
        conn.Close();

        return ds.Tables[0];
    }
}
categoryFilter
变量可能导致查询返回0行


最好的处理方法是什么?我想手动创建只包含标题行(列名)的DGV,并显示一个消息框,说明没有返回任何行。这可能/可行吗?这是处理这一问题的最佳方式吗?

绑定具有零行的数据表绝对没有问题-不管怎样,它都将具有一组正确类型的列,并且如果AutoGenerateColumns属性为true,它将自动创建列

出现问题的原因很简单,因为您试图访问0,0处的datagridview单元格,而不确保它存在,因此您可以:

但是你应该把这句话完全去掉——反正它什么作用也没有;它不会隐藏左上角的蓝色选择突出显示,并且新绑定的datagridview的左上角单元格已经
Selected=false
,因此除了这行代码的异常之外,您不会获得任何其他结果

如果要在DGV未聚焦时隐藏蓝色选择突出显示,请将单元格的
样式。SelectionBackColor
设置为与其
样式相同。BackColor
,但一定要将其设置为用户聚焦网格时可见的内容,否则用户将难以理解为什么无法使该单元格突出显示

如果要删除允许添加新值的重影行,请将
allowUserToAddress
设置为false

如果要让用户知道最近的搜索中没有行,请在DGV顶部放置一个标签,标签上写着“Your search”which'returned no results”,并根据是否有行设置其可见性:

lblNoResults.Text = $"Your search '{categoryFilter}' returned no rows";
lblNoResults.Visible = dtCategories.Rows.Count == 0;
最后,当您只需要一个数据表时,不需要使用数据集。数据适配器可以填充数据表;使用数据集无需付出额外的浪费——这就像使用
列表
并访问它的第0个元素,而您只需要
字符串
。您也不需要打开/关闭连接-dataadapter自己知道如何做。它足够智能,不会关闭在其他地方打开的连接(如果有正在进行的事务):


由于
da.Fill(ds)
返回添加的行数,您可以修改
GetDgvData()
以返回此值(返回元组
(DataTable,int)
ref
参数),或使用返回的DataTable检查它包含的行数。如果是
0
,则不要执行接触DGV单元格的代码。使用Count:If(this.dtCategories.Count()>0)“我想手动创建DGV,只使用标题行(列名)”?好的,我不熟悉Npgsql提供程序,但是您是说,
da.Fill
命令在没有返回行时没有填充DataTable模式(列)?带有架构的空表可以指定为DGV数据源,以便自动创建列,但不会显示as行。@TnTinMn,我是沿着“空表”路线考虑的。其他人提到了如何检查0行,我想我可以添加一个与DGV大小相同的TableLayoutPanel,TLP中的标题看起来像填充的DGV中的标题。然后加载隐藏了表的表单,并在没有要返回的行时显示它(并隐藏DGV)。在演示方面,如果做得好,用户会觉得它天衣无缝。你的想法?你在冒险通过征求意见来结束你的问题。也就是说,我将使用方向=水平的SplitContainer控件。配电盘1将容纳完全对接的DGV。Panel2将放置一个标签,该标签与AutoSize=false和TextAlign=MiddleCenter完全对接。分配DGV数据源后,设置SplitContainer SplitterDistance=DGV.GetPreferredSize(Size.Empty).Height和
SplitContainer.Panel2Collapsed=dt.Rows.Count>0
。将标签文本设置为您想要显示的任何消息。哇!非常好的观点,感谢您花时间来了解所有这些——特别是因为我的问题中没有直接问到很多问题!
lblNoResults.Text = $"Your search '{categoryFilter}' returned no rows";
lblNoResults.Visible = dtCategories.Rows.Count == 0;
    DataTable dt = new DataTale();
    using (NpgsqlDataAdapter da = new NpgsqlDataAdapter(cmd))
    {
        da.Fill(dt);
    }
    return dt;