在空的网格上显示网格视图底部?

12

我想知道在GridView没有数据时,最好且最简单的方法是如何显示表格底部以进行数据输入?

6个回答

16

将您的数据源设置为GridView所绑定的对象类型,其中一个对象填充了空值,然后隐藏该DataRow。

编辑:因为您使用的是datatable...

DataTable dt = new DataTable();

// Define all of the columns you are binding in your GridView
dt.Columns.Add("AColumnName");
...
...

DataRow dr = dt.NewRow();
dt.Rows.Add(dr);

myGridView.DataSource = dt;
myGridView.DataBind();

我正在使用数据表,你有任何示例吗? - Zo Has
3
我感觉这个方法有些繁琐,但是我时间不够了,所以这个修正对我有用。我必须通过添加myGridView.Rows[0].visible = false来隐藏在网格视图中的“空”行。 - marty

9
更加优雅的做法是扩展GridView并添加ShowFooterWhenEmpty属性,这样您就不必在各处实现自定义代码。
Imports System.Web.UI.WebControls
Imports System.ComponentModel

Namespace UI.WebControls
Public Class GridViewExtended
    Inherits GridView

    Private _footerRow As GridViewRow

    <DefaultValue(False), Category("Appearance"), Description("Include the footer when the table is empty")> _
    Property ShowFooterWhenEmpty As Boolean

    <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Browsable(False)> _
    Public Overrides ReadOnly Property FooterRow As GridViewRow
        Get
            If (Me._footerRow Is Nothing) Then
                Me.EnsureChildControls()
            End If
            Return Me._footerRow
        End Get
    End Property

    Protected Overrides Function CreateChildControls(ByVal dataSource As System.Collections.IEnumerable, ByVal dataBinding As Boolean) As Integer
        Dim returnVal As Integer = MyBase.CreateChildControls(dataSource, dataBinding)
        If returnVal = 0 AndAlso Me.ShowFooterWhenEmpty Then
            Dim table As Table = Me.Controls.OfType(Of Table)().First
            Me._footerRow = Me.CreateRow(-1, -1, DataControlRowType.Footer, DataControlRowState.Normal, dataBinding, Nothing, Me.Columns.Cast(Of DataControlField).ToArray, table.Rows, Nothing)
            If Not Me.ShowFooter Then
                _footerRow.Visible = False
            End If
        End If
        Return returnVal
    End Function

    Private Overloads Function CreateRow(ByVal rowIndex As Integer, ByVal dataSourceIndex As Integer, ByVal rowType As DataControlRowType, ByVal rowState As DataControlRowState, ByVal dataBind As Boolean, ByVal dataItem As Object, ByVal fields As DataControlField(), ByVal rows As TableRowCollection, ByVal pagedDataSource As PagedDataSource) As GridViewRow
        Dim row As GridViewRow = Me.CreateRow(rowIndex, dataSourceIndex, rowType, rowState)
        Dim e As New GridViewRowEventArgs(row)
        If (rowType <> DataControlRowType.Pager) Then
            Me.InitializeRow(row, fields)
        Else
            Me.InitializePager(row, fields.Length, pagedDataSource)
        End If
        If dataBind Then
            row.DataItem = dataItem
        End If
        Me.OnRowCreated(e)
        rows.Add(row)
        If dataBind Then
            row.DataBind()
            Me.OnRowDataBound(e)
            row.DataItem = Nothing
        End If
        Return row
    End Function

End Class
End Namespace

1
C#版本 https://dev59.com/bUjSa4cB1Zd3GeqPBwE4#10891744 - Aximili

4
另一种解决方案是在数据源中始终添加一个虚拟行,“标记”该行具有特定的值,然后在 RowDataBound 时隐藏该行。
更准确地说,在查询的 SELECT 子句的末尾添加列“,0 AS dummyRow”,然后 UNION ALL 完整语句。
SELECT NULL AS column1, NULL AS column2,...,NULL AS columnN, 1 AS dummyRow

一旦您完成查询(所有这些都可以在SQLDataSource或DAL对象中完成),则网格的代码将类似于以下内容:

Protected Sub MyGridView_RowDataBound(sender As Object, e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles MyGridView.RowDataBound
    If (e.Row.RowType = DataControlRowType.DataRow) AndAlso (Not e.Row.DataItem Is Nothing) AndAlso (CInt(e.Row.DataItem("dummyRow")) = 1) Then
          e.Row.Visible = False
    End If
End Sub

这种解决方案显然会带来一些开销,因为它将对结果的每一行都进行检查,更不用说你必须更改SELECT查询了,但它也具有不需要动态更改数据集(就像第一个示例中那样)并且不需要太多代码或部署自定义控件库到您的Web项目的优点。


1
你可以创建一个“空”行并将其隐藏起来:
if (list != null && list.Any())
        {
            gridView.DataSource = list;
            gridView.DataBind();
        }
        else
        {
            MyCustomClass item = new MyCustomClass(){Id = 0, Name = "(No Data Rows)", Active = false};
            List<MyCustomClass> l = new List<MyCustomClass>();
            l.Add(item);
            gridView.DataSource = l;
            gridView.DataBind();
            gridView.Rows[0].Visible = false;
        }

1

另外一点,如果您想有条件地显示网格的标题和页脚或显示空数据文本/模板,则可以在隐藏上述代码中的行之后检查您的条件,并在必要时删除该行。然后,代码将类似于以下内容:

 Protected Sub MyGridView_RowDataBound(sender As Object, e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles MyGridView.RowDataBound
      If (e.Row.RowType = DataControlRowType.DataRow) AndAlso (Not e.Row.DataItem Is Nothing) AndAlso (CInt(e.Row.DataItem("dummyRow")) = 1) Then
            e.Row.Visible = False
      If (ConditionToShowEmptyDataTemplate) Then
           CType(e.Row.DataItem, System.Data.DataRowView).Delete()
           CType(e.Row.Parent, System.Web.UI.WebControls.Table).Rows.Remove(e.Row)
      End If
 End Sub

请注意,这里我们删除了DataItem行(因为在post-backs时,GridView可能会重新绘制自身而不重新绑定数据),以及GridView行本身(因为此时该行已经在网格的Childtable中,我们不想要它)。
最后,如果隐藏的虚拟记录在网格视图中有其他数据时引起其他问题(例如,糟糕的分页),您可以使用类似的代码在网格视图具有更多行时删除虚拟行。

0

理想情况下,只有在表中还没有记录时才显示虚拟行。因此,请将SelectCommand设置为以下内容:

SELECT [ID], FirstName, LastName, Email FROM Customers union SELECT 0 [ID], '' FirstName, '' LastName, '' Email where 0 in (SELECT COUNT(1) from Customers)

这样,如果计数> 0,则不会返回虚拟行。

请注意,虚拟行中没有FROM子句。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接