当父Gridview通过编程数据绑定时,下拉列表会丢失SelectedIndexChanged

时间:2015-01-13 16:59:20

标签: asp.net vb.net gridview drop-down-menu event-handling

尝试研究这个问题,但找不到类似的问题却没有取得任何成功。

我有一个gridview,其中包含用户列表和可用权限下拉列表,允许用户更改其他用户的权限(取决于一组内置的业务逻辑)。我最近添加了"过滤"的功能。用户,以帮助使其更易于管理,但现在SelectedIndexChanged事件不起作用,页面按预期回发,但它什么都不做。代码

<asp:UpdatePanel ID="upUsers" runat="server">
    <ContentTemplate>
        <asp:Table ID="tFilters" runat="server" HorizontalAlign="Center">
            <asp:TableRow VerticalAlign="Top">
                <asp:TableCell CssClass="sidepadding10"><b>Filters: </b></asp:TableCell>
                <asp:TableCell CssClass="sidepadding10">
                    Permission Level<br />
                    <asp:DropDownList ID="ddlFilterPermission" runat="server"
                            DataSourceID="sdsPermission" 
                            DataTextField="PermissionName" 
                            DataValueField="PermissionLevelID"
                            AutoPostBack="true" AppendDataBoundItems="True">
                        <asp:ListItem Text="Filter By Permission" Value="0"></asp:ListItem>
                    </asp:DropDownList>
                </asp:TableCell>
                <asp:TableCell CssClass="sidepadding10">
                    Unit<br />
                    <asp:DropDownList ID="ddlFilterUnits" runat="server"
                            DataSourceID="sdsUnit" 
                            DataTextField="UnitName" 
                            DataValueField="UnitID"
                            AutoPostBack="true" AppendDataBoundItems="True">
                        <asp:ListItem Text="Filter By Unit" Value="0"></asp:ListItem>
                    </asp:DropDownList>
                </asp:TableCell>
            </asp:TableRow>
        </asp:Table>
        <asp:GridView ID="gvUsers" runat="server" DataSourceID="sdsUsers" AutoGenerateColumns="false" PageSize="50" HorizontalAlign="Center">
            <Columns>
                <asp:BoundField HeaderText="User" DataField="FkUser" HeaderStyle-CssClass="hidden" ItemStyle-CssClass="hidden" />
                <asp:BoundField HeaderText="Permission Level" DataField="FkLevel" HeaderStyle-CssClass="hidden" ItemStyle-CssClass="hidden" />
                <asp:TemplateField>
                    <HeaderTemplate>
                        User (PUID)
                    </HeaderTemplate>
                    <ItemStyle CssClass="sidepadding10" />
                    <ItemTemplate>
                        <asp:Label ID="lUser" runat="server" Text='<%# Eval("FkUser")%>'></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField>
                    <HeaderTemplate>
                        Permission Level
                    </HeaderTemplate>
                    <ItemStyle CssClass="sidepadding10" />
                    <ItemTemplate>
                        <asp:DropDownList ID="ddlPermission" runat="server"
                            DataSourceID="sdsPermission" DataTextField="PermissionName" DataValueField="PermissionLevelID" SelectedValue='<%# Eval("FkLevel")%>'
                            AutoPostBack="true"
                            OnSelectedIndexChanged="ddlPermission_SelectedIndexChanged"
                            OnDataBound="ddlPermission_DataBound">
                        </asp:DropDownList>
                        <asp:Label ID="lPermission" runat="server" Visible="false"></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField>
                    <HeaderTemplate>
                        Sub Permission
                    </HeaderTemplate>
                    <ItemStyle CssClass="sidepadding10" />
                    <ItemTemplate>
                        <asp:DropDownList ID="ddlSubPermission" runat="server"
                            AutoPostBack="true" AppendDataBoundItems="true"
                            OnSelectedIndexChanged="ddlSubPermission_SelectedIndexChanged">
                            <asp:ListItem Text="Select Sub-Permission Group" Value="0"></asp:ListItem>
                        </asp:DropDownList>
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
            <PagerStyle CssClass="footer" />
            <PagerTemplate>
                <asp:GridViewPager ID="GridViewPager1" runat="server" />
            </PagerTemplate>
        </asp:GridView>
        <asp:Literal ID="Literal1" runat="server"></asp:Literal>
        <asp:SqlDataSource ID="sdsUsers" runat="server"
            ConnectionString="<%$ ConnectionStrings:ApplicationConnectionString %>"
            SelectCommand="SELECT FkUser, FkLevel, FkUnit, FkRegion, FkSection FROM CMT.dbo.UserPermissions UP INNER JOIN Common.dbo.Users U ON UP.FkUser = U.UserID ORDER BY FkLevel Desc, Surname, Forename"></asp:SqlDataSource>
        <asp:SqlDataSource ID="sdsPermission" runat="server"
            ConnectionString="<%$ ConnectionStrings:ApplicationConnectionString %>"
            SelectCommand="SELECT PermissionLevelID, PermissionName FROM PermissionLevels">
            <SelectParameters>
                <asp:SessionParameter SessionField="CMT#PermissionLevel" Name="Permission" />
            </SelectParameters>
        </asp:SqlDataSource>
        <asp:SqlDataSource ID="sdsUnit" runat="server"
            ConnectionString="<%$ ConnectionStrings:ApplicationConnectionString %>"
            SelectCommand="SELECT DISTINCT [UnitID], [UnitName] FROM Units U INNER JOIN UserPermissions UP ON U.UnitID = UP.FkUnit ORDER BY UnitName">
        </asp:SqlDataSource>
    </ContentTemplate>
</asp:UpdatePanel>

背后的代码

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Dim Unit As String = ddlFilterUnits.SelectedValue
    Dim Permission As String = ddlFilterPermission.SelectedValue

    sdsPermission.SelectParameters.Clear()
    If ddlFilterUnits.SelectedValue = 0 And ddlFilterPermission.SelectedValue = 0 Then
        sdsUsers.SelectCommand = "SELECT FkUser, FkLevel, FkUnit, FkRegion, FkSection FROM CMT.dbo.UserPermissions UP INNER JOIN Common.dbo.Users U ON UP.FkUser = U.UserID ORDER BY FkLevel Desc, Surname, Forename"
    ElseIf ddlFilterPermission.SelectedValue = 0 And ddlFilterUnits.SelectedValue > 0 Then
        sdsUsers.SelectParameters.Add("Unit", ddlFilterUnits.SelectedValue)
        sdsUsers.SelectCommand = "SELECT FkUser, FkLevel, FkUnit, FkRegion, FkSection FROM CMT.dbo.UserPermissions UP INNER JOIN Common.dbo.Users U ON UP.FkUser = U.UserID WHERE FkUnit = @Unit ORDER BY FkLevel Desc, Surname, Forename"
    ElseIf ddlFilterPermission.SelectedValue > 0 And ddlFilterUnits.SelectedValue = 0 Then
        sdsUsers.SelectParameters.Add("Permission", ddlFilterPermission.SelectedValue)
        sdsUsers.SelectCommand = "SELECT FkUser, FkLevel, FkUnit, FkRegion, FkSection FROM CMT.dbo.UserPermissions UP INNER JOIN Common.dbo.Users U ON UP.FkUser = U.UserID WHERE FkLevel = @Permission ORDER BY FkLevel Desc, Surname, Forename"
    ElseIf ddlFilterPermission.SelectedValue > 0 And ddlFilterUnits.SelectedValue > 0 Then
        sdsUsers.SelectParameters.Add("Unit", ddlFilterUnits.SelectedValue)
        sdsUsers.SelectParameters.Add("Permission", ddlFilterPermission.SelectedValue)
        sdsUsers.SelectCommand = "SELECT FkUser, FkLevel, FkUnit, FkRegion, FkSection FROM CMT.dbo.UserPermissions UP INNER JOIN Common.dbo.Users U ON UP.FkUser = U.UserID WHERE FkUnit = @Unit AND FkLevel = @Permission ORDER BY FkLevel Desc, Surname, Forename"
    End If
    sdsUsers.DataBind()
    gvUsers.DataBind()

End Sub

Private Sub gvUsers_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles gvUsers.RowDataBound
    If e.Row.RowType = DataControlRowType.DataRow Then

        sqlParams.Clear()
        sql = "SELECT Forename, Surname, PUID FROM Users WHERE UserID = @UID"
        SQLDB.addParameterToList(sqlParams, "@UID", e.Row.DataItem(0).ToString)
        dt = SQLDB.fetchMultipleValues(sql, guestDB, sqlParams)
        Dim user As String = dt.Rows(0).Item("surname").ToString.ToUpper & ", " & dt.Rows(0).Item("Forename") & " (" & dt.Rows(0).Item("PUID") & ")"
        Dim l As Label = DirectCast(e.Row.Cells(2).FindControl("lUser"), Label)
        l.Text = user

        Dim ddlPermission As DropDownList = DirectCast(e.Row.Cells(3).FindControl("ddlPermission"), DropDownList)
        AddHandler ddlPermission.SelectedIndexChanged, AddressOf ddlPermission_SelectedIndexChanged

        Dim ddlSubPermission As DropDownList = DirectCast(e.Row.Cells(4).FindControl("ddlSubPermission"), DropDownList)
        Dim subPermission As String = ""
        Select Case e.Row.Cells(1).Text.ToString
            Case "2"
                subPermission = e.Row.DataItem(2).ToString
                sql = "SELECT UnitID as ID, UnitName as Name FROM Units ORDER BY UnitName"
            Case "3"
                subPermission = e.Row.DataItem(3).ToString
                sql = "SELECT RegionID as ID, RegionName as Name FROM Regions ORDER BY RegionName"
            Case "4"
                subPermission = e.Row.DataItem(4).ToString
                sql = "SELECT SectionID as ID, SectionTitle as Name FROM Sections ORDER BY SectionTitle"
        End Select

        ddlSubPermission.Items.Clear()

        Select Case e.Row.Cells(1).Text.ToString
            Case "2", "3", "4"
                dt = SQLDB.fetchMultipleValues(sql, userDB)
                ddlSubPermission.DataSource = dt
                ddlSubPermission.DataValueField = "ID"
                ddlSubPermission.DataTextField = "Name"
                ddlSubPermission.DataBind()
                ddlSubPermission.Visible = True
                ddlSubPermission.SelectedValue = subPermission
            Case Else
                ddlSubPermission.Visible = False
        End Select
    End If
End Sub

Protected Sub ddlPermission_SelectedIndexChanged(sender As Object, e As EventArgs)
    Dim ddl As DropDownList = DirectCast(sender, DropDownList)
    Dim gvr As GridViewRow = DirectCast(ddl.Parent.Parent, GridViewRow)
    Dim l As Label = DirectCast(gvr.Cells(2).FindControl("lUser"), Label)

    sqlParams.Clear()
    SQLDB.addParameterToList(sqlParams, "@User", gvr.Cells(0).Text)
    SQLDB.addParameterToList(sqlParams, "@newLevel", ddl.SelectedValue)
    sql = "UPDATE UserPermissions SET FkLevel = @newLevel WHERE FkUser = @User"
    SQLDB.executeSqlCUD(sql, userDB, sqlParams)
    Response.Redirect("~/UserManager.aspx")

End Sub

请注意,这不是所有代码,我只包含部分代码。我很确定它与页面生命周期有关,但我无法弄清楚它为什么会按原样行事。

非常感谢任何帮助

1 个答案:

答案 0 :(得分:0)

您正在进行数据绑定,并且您未正确实施过滤器。

关于数据绑定:如果由于更改过滤器DDL而发生回发,则调用sdsUsers.DataBind和gvUsers.DataBind,这是过度的。由于控制事件发生在数据绑定事件之前,因此绑定#1和#2

由于您提供了Gridview DataSourceID,因此Gridview将自动对每个回发进行数据绑定。那就是#5。

注意我说#5,你还为你的两个&#34;过滤器&#34;提供了一个DataSourceID。 ddls,所以他们也数据绑定,并且因为它们出现在控件层次结构中的gridview之前,所以它们首先进行数据绑定,即绑定#3和#4。但是 - 有关于DDL的事情:

来自MSDN Library: ListControl.SelectedIndex Property

  

没有专门保存SelectedIndex属性的值   回发。它使用SelectedValue属性在回发时恢复。   例如,如果SelectedValue属性为4,则在回发时,   SelectedIndex属性设置为ListItem对象的索引   具有Value属性4.如果多个ListItem对象具有   Value属性为4,Items集合中的第一项是   地选择。

在您的代码中,我会检查您是否在ddl的任何位置执行了明确的操作,这将有效地清除所有先前选择的值。

关于过滤:它内置于SqlDataSource控件中。您不是通过指定新的选择命令来完成此操作,而是通过为整个数据集提供过滤条件。查看SqlDataSource Filter Parameters


附录:2015年1月14日下午12:20

对误解您引用的DDL表示歉意。

仅供参考:DDL 一个ListControl。看一下继承层次结构。

关于丢失的事件,无论您选择过滤器,您的Page_Load事件都会强制重新绑定(两次)

此时所有赌注都已关闭,因为Gridview中的嵌入式DDL也将被反弹,这意味着嵌入式DDL的所有事件现在都将丢失。

此外,关于Databinding的一句话:不要混淆&#34;数据绑定&#34;用&#34;点击数据库。&#34;在页面生命周期PreRender事件期间,每个设置了 DataSourceID 的Databound控件都会引发它的Databound事件,更不用说当您显式调用Databind()时。根据您为缓存设置的规则,缓存仅限制需要完整往返数据库的频率。