使用 vb.net 根据 SQL 数据库中存在的记录动态显示/隐藏 DataGrid 按钮列时遇到问题

Posted

技术标签:

【中文标题】使用 vb.net 根据 SQL 数据库中存在的记录动态显示/隐藏 DataGrid 按钮列时遇到问题【英文标题】:Having trouble dynamically show/hide DataGrid buttoncolumn based on record existing in SQL database using vb.net 【发布时间】:2015-05-06 23:35:09 【问题描述】:

我正在使用 Visual Studio 2008 和 vb.net。我有一个包含几列的数据网格,有问题的列是一个 ButtonColumn 控件。当前按钮出现在每一行上,然后链接到另一个页面,其中显示有关名称的数据(在另一列中)被选中。问题是当下一页上的查询不包含所选行的数据时,页面会抛出错误。

我的(首选)解决方案是在 ItemDataBound 事件期间(在切换页面之前)首先检查记录是否存在,并将按钮隐藏在不存在记录的行中,并在它们存在的位置显示按钮。问题是按钮的显示和隐藏不一致。

我不是 vb 程序员,谁能检查我的代码,看看我哪里出错了。

我已经咨询了谷歌并使用这些链接来了解其中的一些内容: http://www.codeproject.com/Articles/8666/Practical-use-of-the-DataGrid-s-ItemDataBound-even

http://www.thescarms.com/dotnet/WebDataGrid.aspx

更新: 解决方案在代码 #1 和 html 中进行了更新。 SQL

ALTER PROCEDURE [dbo].[VerifyRecords] 
    @Name VarChar (50),
    @RecordExists Int output
AS
BEGIN
    SET NOCOUNT ON;

   SELECT top 1 * from tblRecords where Name = @Name

   If @@ROWCOUNT = 0 
    begin
        Select @RecordExists = 5 --record does not exist
    end
   else
    begin
        Select @RecordExists = 1  --record exists
    end  

    -- --ALTERNATIVE QUERY
    --if not exists (select 1 from tblRecords where Name = @Name)
    --  begin
    --      Select @RecordExists = 5    --print 'no record found'
    --  end
    --else
    --  begin 
    --      Select @RecordExists = 1    --print 'record exists'
    --  end
END

enter code here

1.代码在调用类

Protected Sub DataGrid1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles DataGrid1.ItemDataBound

               If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then

                Dim strName As String = ""  
                Dim blnHasRecord As Boolean

                   ' *** UPDATED CODE HERE ***
                   Dim lblName As Label = e.Item.FindControl("lblName")
                   strName = lblName.Text.ToString()

                    Dim oRecord As DataAccessLib.SqlConn = New DataAccessLib.SqlConn()

                    blnHasRecord = oRecord.VerifyRecordExists(strName)
                    DirectCast(e.Item.Cells(9).Controls(0), Button).Visible = blnHasRecord              
            End If
        End Sub

2.代码在数据访问类

Function VerifyRecordExists (ByVal name As String) As Boolean

        Try

            Dim recordExists As Boolean

            Dim result As Int32  

            'connection
            Using conStr As New SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("SomeConnectionString").ConnectionString)

                'open connection
                conStr.Open()

                'command
                Dim cmdVerifyRecordExists As SqlClient.SqlCommand = New SqlClient.SqlCommand("VerifyRecordExists", conStr)
                cmdVerifyRecordExists.CommandType = CommandType.StoredProcedure

                'input parameter
                cmdVerifyRecordExists.Parameters.Add("@Name", SqlDbType.VarChar).Value = name

                'output parameter
                cmdVerifyRecordExists.Parameters.Add("@RecordExists", SqlDbType.Int)
                cmdVerifyRecordExists.Parameters("@RecordExists").Direction = ParameterDirection.Output 

                'execute query 
                cmdVerifyRecordExists.ExecuteNonQuery()
                result = cmdVerifyRecordExists.Parameters("@RecordExists").Value

            End Using

            If (name <> Nothing) Then  

                If (result = 5) Then 'result = 5; no records found
                    recordExists = False
                Else
                    ' result = 1; records found
                    recordExists = True
                    Return recordExists
                End If
            End If

        Catch ex As System.Data.SqlClient.SqlException

            ' code here removed for breivity

        End Try
    End Function

3.CODE绑定DataGrid

Sub getRecords(ByVal strSortField As String)

    Dim sortdir As Integer

    DataGrid1.DataSource = Nothing

    Using conStr As New SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("SomeConnectionString").ConnectionString)

        Try 
            If USERLEVEL > 2 Then 

                conStr.Open()

                Dim cmdSelectRecords As New SqlCommand("SelectAllNames", conStr)

                cmdSelectRecords.CommandType = CommandType.StoredProcedure 

                SqlDataAdapter1.Fill(DsRecords1) 
                Dim objDataView As DataView = DsRecords1.Tables("vwRecordsList").DefaultView 

                DataGrid1.DataSource = Nothing 

                DataGrid1.DataSource = objDataView 

                If Session("sortdir") = Nothing Then
                    Session("sortdir") = 1  ' 1=ASC, 0=DESC
                Else
                    sortdir = Session("sortdir")
                End If

                If sortdir = 1 Then
                    Session("sortdir") = 0
                    objDataView.Sort = strSortField & " DESC"

                ElseIf sortdir = 0 Then
                    Session("sortdir") = 1
                    objDataView.Sort = strSortField & " ASC"

                End If

                DataGrid1.DataBind() 

            ElseIf USERLEVEL = 2 Then 

                Dim cmdSelectRecords As New SqlCommand("SelectNamesBySuper", conStr)

                cmdSelectRecords.CommandType = CommandType.StoredProcedure   
                cmdSelectRecords.Parameters.Add("@UID", SqlDbType.Int).Value = uID 

                SqlDataAdapter1.Fill(DsRecords1)

                Dim objDataView As DataView = DsRecords1.Tables("vwRecordsList ").DefaultView

                DataGrid1.DataSource = Nothing
                DataGrid1.DataSource = objDataView

                If Session("sortdir") = Nothing Then
                    Session("sortdir") = 1

                Else
                    sortdir = Session("sortdir")

                End If

                If sortdir = 1 Then

                    Session("sortdir") = 0
                    objDataView.Sort = strSortField & " DESC"

                ElseIf sortdir = 0 Then

                    Session("sortdir") = 1
                    objDataView.Sort = strSortField & " ASC"

                End If

                DataGrid1.DataBind() 

            Else
                Response.Redirect("AccessDenied.aspx")

            End If
        Catch ex As System.Data.SqlClient.SqlException
' error code left out for demo purposes
                End If

            End Try

        End Using

    End Sub

HTML 我只提供 DataGrid1 的相关列,因为网格本身加载得很好。是我在后面的代码中对这一列的修改还不正确。

更新:我用 TemplateColumn 替换了 boundcolumn:

<%--<asp:BoundColumn DataField="Name" HeaderText=" Name" SortExpression="Name" Visible="False" />--%>
<asp:TemplateColumn>
<ItemTemplate>
<asp:Label id="lblName" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Name") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateColumn>

【问题讨论】:

按钮何时显示和隐藏不一致?页面加载后或页面中发生类似按钮时。 在 DirectCast 上尝试 GridItem.Cells(9).Controls(0) 而不是更改 e.Item.Cells(9).Controls(0) 哦,很好@DanielVorph,这成功了!请给出答案,我会接受。但是现在,当使用 Name 列时,第一行变成了最后一行,并且在应该隐藏时错误地显示了一个按钮。所有其他行以 ASC 或 DESC 顺序正确显示按钮/无按钮。当我求助于原始(asc)排序时,第一行再次正确。如果有兴趣看一下,我为此发布了排序代码 #3。 Put DirectCast(GridItem.Cells(9).Controls(0), Button).Visible = blnHasRecord quit if else 语句,你调试最后一行发生了什么,strName 值是多少? ItemDataBound 事件会为数据源中的每一行触发,然后您在其中有一个循环,您应该退出循环并仅使用当前项目 e.Item 【参考方案1】:

我希望可以发布 DanielVorph 提供的答案。 “数据源中的每一行都会触发 ItemDataBound 事件,然后您在其中有一个循环,您应该退出循环并仅使用当前项目 e.Item– DanielVorphMay 8 at 21:21”。 在除此之外,我将 DataGrid1 中的 BoundColumn 替换为 TemplateColumn

VB.NET:

Protected Sub DataGrid1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles DataGrid1.ItemDataBound

    'Get only non header or footer rows
    If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then

        Dim strName As String                               'column[2]
        Dim blnHasRecord As Boolean

        'get Name
        Dim lblName As Label = e.Item.FindControl("lblName")
        strName = lblName.Text.ToString()

        'query sql - does record exist for this Name?
        Dim oRecord As DataAccessLib.SqlConn = New DataAccessLib.SqlConn()
        blnHasRecord = oRecord. VerifyRecordExists (strName)

        'Show or hide button based on records existence
        DirectCast(e.Item.Cells(9).Controls(0), Button).Visible = blnHasRecord  'column[9]
    End If

End Sub

ASPX: 删除此类列:

<asp:BoundColumn DataField="Name" HeaderText="Name" SortExpression="Name" Visible="False" />

添加这种类型的列:

<asp:TemplateColumn>
   <ItemTemplate>
      <asp:Label id="lblName" runat="server" Text='<%#DataBinder.Eval 
(Container.DataItem, "Name") %>'>
      </asp:Label>
   </ItemTemplate>
</asp:TemplateColumn>

【讨论】:

以上是关于使用 vb.net 根据 SQL 数据库中存在的记录动态显示/隐藏 DataGrid 按钮列时遇到问题的主要内容,如果未能解决你的问题,请参考以下文章

从 VB.net 连接到 SQL 数据库时,“行/列不存在数据”

VB.NET 不在 sql server 2008 express 中创建数据库

使用 vb.net 从 excel 文件更新 SQL 表

VB.Net根据下拉文本选择隐藏特定的gridview列

SQL插入语句语法错误VB.net

在VB.net中,连接SQL Server数据库的连接字符串的问题。