【问题标题】:asp:Gridview getting focused column/lifecycle issueasp:Gridview 获得焦点列/生命周期问题
【发布时间】:2013-04-09 07:24:31
【问题描述】:

我正在为一组更复杂的功能开发概念证明 (POC) GridView,其中任何给定单元格都填充有文本框,无论它处于正常模式还是编辑模式。当任何给定的文本框获得焦点(选项卡或鼠标)时,该行将设置为编辑状态,并且它在编辑模式下的相应文本框应该获得焦点。一旦该文本框失去焦点,它应该导致对该行进行更新。我让 POC 工作,除了找到一种可行的方法来选择收到焦点的列(“文本框”),我认为这是一个生命周期问题,但没有提出任何好的解决方法。请记住,这是一个 POC,我所做的一些事情可能不是最佳实践,因为它是一种快速而肮脏的方式来使其工作。如有任何建议,我将不胜感激。

表格:

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="StandardContactEditor.aspx.vb" Inherits="EditableGridView.StandardContactEditor" EnableEventValidation="false" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:GridView ID="contactsDataGrid"
                    AllowPaging="true" PageSize="5"
                    DataKeyNames="ID"
                    AutoGenerateColumns="false"

                    runat="server">
                <Columns>
                    <asp:TemplateField HeaderText="First Name">
                        <ItemTemplate>
                            <asp:TextBox ID="txtFirstName" Text='<%# Bind("FirstName") %>' runat="server" />
                        </ItemTemplate>
                        <EditItemTemplate>
                            <asp:TextBox ID="txtFirstNameEdit" Text='<%# Bind("FirstName") %>' runat="server" />
                        </EditItemTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="Last Name">
                        <ItemTemplate>
                            <asp:TextBox ID="txtLastName" Text='<%# Bind("LastName") %>' runat="server" />
                        </ItemTemplate>
                        <EditItemTemplate>
                            <asp:TextBox ID="txtLastNameEdit" Text='<%# Bind("LastName") %>' runat="server" />
                        </EditItemTemplate>
                    </asp:TemplateField>
                </Columns>
            </asp:GridView>
        </div>
    </form>
</body>
</html>

代码:

Imports FileHelpers

Public Class StandardContactEditor
    Inherits System.Web.UI.Page

    private fileName As String = "C:\TestFiles\TestContacts.csv"
    Private records As List(Of ContactCSV)

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If Not IsPostBack
            BindGridData()
        End If
    End Sub

    Private Sub BindGridData()
        PopulateRecords()

        Me.contactsDataGrid.DataSource = records
        Me.contactsDataGrid.DataBind()
    End Sub

    Protected Sub RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs) Handles contactsDataGrid.RowDataBound
        e.Row.Attributes("onfocus") = ClientScript.GetPostBackClientHyperlink(contactsDataGrid, "Edit$" + e.Row.DataItemIndex.ToString(), false)

        If Not ((e.Row.RowState = DataControlRowState.Edit) _
                Or (e.Row.RowState = (DataControlRowState.Alternate Or DataControlRowState.Edit)))
            Try
                ' First Name Column
                Dim firstNameTb As TextBox = e.Row.FindControl("txtFirstName")
                ' firstNameTb.Attributes("onfocus") = ClientScript.GetPostBackClientHyperlink(contactsDataGrid, "Edit$" + e.Row.DataItemIndex.ToString(), false)

                                    ' ISSUE CAUSED BY APPENDING "000" - Used for col/textbox identification
                firstNameTb.Attributes("onfocus") = ClientScript.GetPostBackClientHyperlink(contactsDataGrid, "Edit$" + e.Row.DataItemIndex.ToString() + "000", false)
            Catch ex As Exception
                Console.WriteLine()
            End Try

            Try
                Dim lastNameTb As TextBox = e.Row.FindControl("txtLastName")
                ' lastNameTb.Attributes("onfocus") = ClientScript.GetPostBackClientHyperlink(contactsDataGrid, "Edit$" + e.Row.DataItemIndex.ToString(), false)

                                    ' ISSUE CAUSED BY APPENDING "001" - Used for col/textbox identification
                lastNameTb.Attributes("onfocus") = ClientScript.GetPostBackClientHyperlink(contactsDataGrid, "Edit$" + e.Row.DataItemIndex.ToString() + "001", false)
            Catch ex As Exception
            End Try
        End If
    End Sub

    Protected Sub RowEditing(ByVal sender As Object, ByVal e As GridViewEditEventArgs) Handles contactsDataGrid.RowEditing
        contactsDataGrid.EditIndex = (e.NewEditIndex / 1000)
        Dim col As Integer = (e.NewEditIndex Mod 1000)

        ' contactsDataGrid.EditIndex = e.NewEditIndex

        BindGridData()

        Dim fntb As TextBox = contactsDataGrid.Rows(contactsDataGrid.EditIndex).FindControl("txtFirstNameEdit")
        fntb.Attributes("onblur") = ClientScript.GetPostBackClientHyperlink(contactsDataGrid, "Update$" + contactsDataGrid.EditIndex.ToString(), false)
        ' fntb.Focus()

        Dim lntb As TextBox = contactsDataGrid.Rows(contactsDataGrid.EditIndex).FindControl("txtLastNameEdit")
        lntb.Attributes("onblur") = ClientScript.GetPostBackClientHyperlink(contactsDataGrid, "Update$" + contactsDataGrid.EditIndex.ToString(), false)
        ' lntb.Focus()

        If(col = 0)
            fntb.Focus()
        Else If(col = 1)
            lntb.Focus()
        End If
    End Sub

    Protected Sub RowUpdating(ByVal sender As Object, ByVal e As GridViewUpdateEventArgs) Handles contactsDataGrid.RowUpdating
                    ' AT THIS POINT THE EDIT FIELDS ARE NOT VISIBLE AND AN EXCEPTION IS THROWN WHEN TRYING TO RETRIEVE THOSE TEXTBOXES

        ' Trying to override here
        contactsDataGrid.EditIndex = (contactsDataGrid.EditIndex / 1000)

        PopulateRecords()

        Dim id As String = contactsDataGrid.DataKeys(e.RowIndex).Value.ToString()

        Dim record As ContactCSV = records.Where(Function(x) x.ID = id).SingleOrDefault()

        Dim firstNameTb As TextBox = contactsDataGrid.Rows(e.RowIndex).FindControl("txtFirstNameEdit")
        record.firstName = firstNameTb.Text

        Dim lastNameTb As TextBox = contactsDataGrid.Rows(e.RowIndex).FindControl("txtLastNameEdit")
        record.lastName = lastNameTb.Text

        WriteRecordsToFile()

        contactsDataGrid.EditIndex = -1

        ' update the actual data
        contactsDataGrid.DataSource = records
        contactsDataGrid.DataBind()
    End Sub

    Protected Sub SelectedColumn(ByVal Sender As Object, ByVal e As EventArgs)
        Console.WriteLine()
    End Sub

    Private Sub PopulateRecords()
        Dim fileEngine As New FileHelperEngine(GetType(ContactCSV))

        Try
            Dim objs As ContactCSV() = fileEngine.ReadFile(fileName)
            records = objs.ToList()
        Catch ex As exception

        End Try
    End Sub

    Private Sub WriteRecordsToFile()
        Dim fileEngine As New FileHelperEngine(GetType(ContactCSV))

        fileEngine.WriteFile(fileName, records)
    End Sub
End Class

【问题讨论】:

    标签: asp.net vb.net gridview


    【解决方案1】:

    这是一个将不熟悉的技术结合起来过度思考解决方案的经典案例。这个想法是建立一个高度响应的(每个字段编辑)页面。没有混合任何内置的 GridView 功能,一个简单的 OnTextChanged 在其他所有内容都被剥离后按我的预期工作。之前发布的代码出现的问题是在 OnBlur 之后,在列标识部分就位的情况下,将一行设置为 Alternate 状态而不是 Alternate 或 Edit 状态。

    表格:

    <%@ Page Language="vb" AutoEventWireup="false" CodeBehind="StandardContactEditor.aspx.vb" Inherits="EditableGridView.StandardContactEditor" EnableEventValidation="true" %>
    
    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <asp:GridView ID="contactsDataGrid"
                        AllowPaging="true" PageSize="5"
                        DataKeyNames="ID"
                        AutoGenerateColumns="false"
    
                        runat="server">
                    <Columns>
                        <asp:TemplateField HeaderText="First Name">
                            <ItemTemplate>
                                <asp:TextBox ID="txtFirstName" Text='<%# Bind("FirstName") %>' OnTextChanged="textBox_TextChanged" AutoPostBack="true" runat="server" />
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField HeaderText="Last Name">
                            <ItemTemplate>
                                <asp:TextBox ID="txtLastName" Text='<%# Bind("LastName") %>' OnTextChanged="textBox_TextChanged" AutoPostBack="true" runat="server" />
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField HeaderText="Phone Number">
                            <ItemTemplate>
                                <asp:TextBox ID="txtPhoneNumber" Text='<%# Bind("PhoneNumber") %>' OnTextChanged="textBox_TextCHanged" AutoPostBack="true" runat="server" />
                            </ItemTemplate>
                        </asp:TemplateField>
                    </Columns>
                </asp:GridView>
            </div>
        </form>
    </body>
    </html>
    

    代码:

    Imports FileHelpers
    
    Public Class StandardContactEditor
        Inherits System.Web.UI.Page
    
        private fileName As String = "C:\TestFiles\TestContacts.csv"
        Private records As List(Of ContactCSV)
    
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            If Not IsPostBack
                BindGridData()
            End If
        End Sub
    
        Private Sub BindGridData()
            PopulateRecords()
    
            Me.contactsDataGrid.DataSource = records
            Me.contactsDataGrid.DataBind()
        End Sub
    
        Protected Sub textBox_TextChanged(ByVal sender As Object, ByVal e As EventArgs)
            PopulateRecords()
    
            Dim tb as TextBox = sender
            Dim row As GridViewRow = tb.Parent.Parent
    
            Dim record As ContactCSV = records.Where(Function(x) x.ID = row.RowIndex).SingleOrDefault()
    
            Dim firstNameTb As TextBox = contactsDataGrid.Rows(row.RowIndex).FindControl("txtFirstName")
            record.firstName = firstNameTb.Text
    
            Dim lastNameTb As TextBox = contactsDataGrid.Rows(row.RowIndex).FindControl("txtLastName")
            record.lastName = lastNameTb.Text
    
            Dim phoneNumberTb As TextBox = contactsDataGrid.Rows(row.RowIndex).FindControl("txtPhoneNumber")
            record.PhoneNumber = phoneNumberTb.Text
    
            WriteRecordsToFile()
        End Sub
    
        Private Sub PopulateRecords()
            Dim fileEngine As New FileHelperEngine(GetType(ContactCSV))
    
            Try
                Dim objs As ContactCSV() = fileEngine.ReadFile(fileName)
                records = objs.ToList()
            Catch ex As exception
    
            End Try
        End Sub
    
        Private Sub WriteRecordsToFile()
            Dim fileEngine As New FileHelperEngine(GetType(ContactCSV))
    
            fileEngine.WriteFile(fileName, records)
        End Sub
    End Class
    

    【讨论】:

    • 我应该提一下,随着可编辑字段数量的增加,性能趋于下降,因为每个字段都有自己的 textBox_TextChanged 自动生成的 javascript 实例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-02
    • 2012-12-29
    • 2011-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多