asp:Gridview获得专注的列/生命周期问题

时间:2013-04-16 18:43:31

标签: asp.net vb.net gridview

我正在开发一个概念验证(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

1 个答案:

答案 0 :(得分:1)

这是一个过度思考解决方案的经典案例,结合了一种不熟悉的技术。我们的想法是建立一个高度响应(每个字段编辑)页面。而不是混合任何内置的GridView功能,一个简单的OnTextChanged工作正如我所期望的其他一切被剥离后。问题结果发布之前发布的代码是在OnBlur之后,列标识部分就位,一行被设置为Alternate状态而不是Alternate Or 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