У меня есть таблица, которая создается в коде позади. В коде vb таблица заполняется на основе данных, возвращаемых из запроса, когда выбрано значение combobox. Код создает строку с двумя ячейками для метки и одну для выпадающего списка для каждой строки в данных. У меня возникли проблемы с сохранением выбранных значений выпадающего списка, которые создаются для каждой строки после обратной передачи.Сохраняющаяся динамическая таблица по обратной обратной связи
Когда таблица изначально заполнена, я храню данные в виде ViewState и воссоздаю таблицу на основе этих настроек в PageLoad. Проблема заключается в том, что каждый раз, когда я изменяю значения для раскрывающихся списков, а затем вызывается обратная передача, нажав «сохранить настройки», все настройки будут неправильно сохранены, потому что они возвращены до того, как будет вызываться даже вызов.
Я ищу, чтобы поддерживать значения по обратной стороне, но все же обновлять значения из базы данных при выборе новой учетной записи. Я попытался несколько способов сделать это и испытал две проблемы с моим кодом:
Когда у меня есть EnableViewState = "true" в таблице в разметке: Когда я выбираю элемент из выпадающего списка, чтобы выбрать новую учетную запись, выбранные значения в выпадающих списках остаются, когда они должны очищаться в это время и использовать новые значения базы данных.
Когда у меня есть EnableViewState = "false" в таблице в разметке: Любой postback сбрасывает dropdownlists в значения своих баз данных. Даже щелкнув «Сохранить», который немедленно отправляет назад, чтобы сохранить значения в базе данных, будет просто сохранять текущие значения базы данных и игнорировать выбранные значения.
код позади:
Imports System.Data.SqlClient
Imports Telerik.Web.UI
Public Class AccountSettings2
Inherits Page
Private _selectedAccountID As Integer
Protected _truckPermissions As List(Of PermissionData2)
Private Sub Page_Init(sender As Object, e As EventArgs) Handles Me.Init
_truckPermissions = New List(Of PermissionData2)
If Not IsNothing(Session("SelectedAccountID")) Then
_selectedAccountID = Session("SelectedAccountID")
End If
If Not IsPostBack Then
Dim dtAccounts As New DataTable("Accounts")
Dim col1 As DataColumn = New DataColumn()
col1.DataType = System.Type.GetType("System.Int32")
col1.ColumnName = "AccountID"
dtAccounts.Columns.Add(col1)
Dim col2 As DataColumn = New DataColumn()
col2.DataType = System.Type.GetType("System.String")
col2.ColumnName = "Name"
dtAccounts.Columns.Add(col2)
Dim row1 As DataRow
Dim row2 As DataRow
Dim row3 As DataRow
Dim row4 As DataRow
row1 = dtAccounts.NewRow()
row1("AccountID") = 1
row1("Name") = "Account 1"
dtAccounts.Rows.Add(row1)
row2 = dtAccounts.NewRow()
row2("AccountID") = 2
row2("Name") = "Account 2"
dtAccounts.Rows.Add(row2)
row3 = dtAccounts.NewRow()
row3("AccountID") = 3
row3("Name") = "Account 3"
dtAccounts.Rows.Add(row3)
row4 = dtAccounts.NewRow()
row4("AccountID") = 4
row4("Name") = "Account 4"
dtAccounts.Rows.Add(row4)
rcbAccounts.DataValueField = "AccountID"
rcbAccounts.DataTextField = "Name"
rcbAccounts.DataSource = dtAccounts
rcbAccounts.DataBind()
End If
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
If _selectedAccountID > 0 Then
rcbAccounts.SelectedValue = _selectedAccountID
SelectAccount(_selectedAccountID)
End If
End If
End Sub
#Region "UI Updates"
Private Sub SelectAccount(accountID As Integer)
_selectedAccountID = accountID
Session("SelectedAccountID") = accountID
CreateTruckPermissionsData(accountID)
End Sub
Private Sub CreateTruckPermissionsData(accessTypeID As Integer)
tblTruckPermissions.Rows.Clear()
_truckPermissions.Add(New PermissionData2(1, "Permission 1", "Permission 1", accessTypeID))
_truckPermissions.Add(New PermissionData2(2, "Permission 2", "Permission 2", accessTypeID))
_truckPermissions.Add(New PermissionData2(3, "Permission 3", "Permission 3", accessTypeID))
_truckPermissions.Add(New PermissionData2(4, "Permission 4", "Permission 4", accessTypeID))
ViewState("_truckPermissions") = _truckPermissions
Dim dtAccessTypes As New DataTable("AccessTypes")
Dim col1 As DataColumn = New DataColumn()
col1.DataType = System.Type.GetType("System.Int32")
col1.ColumnName = "AccessTypeID"
dtAccessTypes.Columns.Add(col1)
Dim col2 As DataColumn = New DataColumn()
col2.DataType = System.Type.GetType("System.String")
col2.ColumnName = "Description"
dtAccessTypes.Columns.Add(col2)
Dim row1 As DataRow
Dim row2 As DataRow
Dim row3 As DataRow
Dim row4 As DataRow
row1 = dtAccessTypes.NewRow()
row1("AccessTypeID") = 1
row1("Description") = "Type 1"
dtAccessTypes.Rows.Add(row1)
row2 = dtAccessTypes.NewRow()
row2("AccessTypeID") = 2
row2("Description") = "Type 2"
dtAccessTypes.Rows.Add(row2)
row3 = dtAccessTypes.NewRow()
row3("AccessTypeID") = 3
row3("Description") = "Type 3"
dtAccessTypes.Rows.Add(row3)
row4 = dtAccessTypes.NewRow()
row4("AccessTypeID") = 4
row4("Description") = "Type 4"
dtAccessTypes.Rows.Add(row4)
For Each pd As PermissionData2 In _truckPermissions
Dim tr As New TableRow()
Dim td As New TableCell()
Dim td2 As New TableCell()
Dim l As New Label()
Dim ddl As New RadDropDownList()
l.Text = pd.Name
ddl.ID = "ddlTruckPermission" + pd.ID.ToString()
ddl.DataTextField = "Description"
ddl.DataValueField = "AccessTypeID"
ddl.DataSource = dtAccessTypes
ddl.DataBind()
ddl.SelectedValue = pd.HasAccess
td.Controls.Add(l)
td2.Controls.Add(ddl)
tr.Cells.Add(td)
tr.Cells.Add(td2)
tblTruckPermissions.Rows.Add(tr)
Next
End Sub
Private Sub RefreshTruckSettings()
If _selectedAccountID = 0 Then
Return
End If
For Each r As TableRow In tblTruckPermissions.Rows
For Each c As Control In r.Cells(1).Controls
If c.ID.Contains("ddlTruckPermission") Then
Dim ddl As RadDropDownList = DirectCast(c, RadDropDownList)
Dim pd As PermissionData2 = _truckPermissions.Find(Function(x) x.ID = Integer.Parse(ddl.ID.Substring(0 + "ddlTruckPermission".Length, ddl.ID.Length - "ddlTruckPermission".Length)))
If Not IsNothing(pd) Then
ddl.SelectedValue = pd.HasAccess
End If
End If
Next
Next
End Sub
#End Region
#Region "Events"
Protected Sub btnSavePermissions_Click(sender As Object, e As EventArgs)
If _selectedAccountID > 0 Then
Dim permissionUpdates As List(Of PermissionUpdate) = New List(Of PermissionUpdate)()
For Each r As TableRow In tblTruckPermissions.Rows
For Each c As Control In r.Cells(1).Controls
If c.ID.Contains("ddlTruckPermission") Then
Dim ddl As RadDropDownList = DirectCast(c, RadDropDownList)
permissionUpdates.Add(New PermissionUpdate(Integer.Parse(ddl.ID.LastIndexOf("ddlTruckPermission")), False, ddl.SelectedValue))
End If
Next
Next
' Code to save permissions to database
End If
End Sub
Protected Sub rcbAccounts_SelectedIndexChanged(sender As Object, e As RadComboBoxSelectedIndexChangedEventArgs)
Dim newIndex As Integer
If (Integer.TryParse(e.Value, newIndex)) Then
SelectAccount(newIndex)
End If
End Sub
#End Region
End Class
<Serializable>
Public Class PermissionData2
Private _id As Integer
Private _name As String
Private _description As String
Private _hasAccess As Integer
Public Property ID() As Integer
Get
Return _id
End Get
Set(value As Integer)
_id = value
End Set
End Property
Public Property Name() As String
Get
Return _name
End Get
Set(value As String)
_name = value
End Set
End Property
Public Property Description() As String
Get
Return _description
End Get
Set(value As String)
_description = value
End Set
End Property
Public Property HasAccess() As Integer
Get
Return _hasAccess
End Get
Set(value As Integer)
_hasAccess = value
End Set
End Property
Public Sub New()
_id = 0
_name = Name
_description = Description
_hasAccess = 0
End Sub
Public Sub New(id As Integer, name As String, description As String, hasAccess As Integer)
_id = id
_name = name
_description = description
_hasAccess = hasAccess
End Sub
End Class
ASPX:
<%@ Page Language="vb" AutoEventWireup="false"
CodeBehind="AccountSettings2.aspx.vb" Inherits="AccountSettings2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<link rel="stylesheet" type="text/css" href="styles/default.css" />
<title>Account Settings</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager runat="server" ID="ScriptManager1"></asp:ScriptManager>
<asp:UpdatePanel id="UpdatePanel1" runat="server" UpdateMode="Always">
<ContentTemplate>
<telerik:RadComboBox ID="rcbAccounts" runat="server" Height="200" Width="200"
DropDownAutoWidth="Enabled" EmptyMessage="Select an Account" HighlightTemplatedItems="true"
EnableLoadOnDemand="true" Filter="Contains"
OnSelectedIndexChanged="rcbAccounts_SelectedIndexChanged" AutoPostBack ="true"
Label="Accounts: " Skin="Office2010Silver" />
<asp:Table ID="tblTruckPermissions" runat="server" EnableViewState="true" />
<asp:Button ID="btnSavePermissions" runat="server" Text="Save" OnClick="btnSavePermissions_Click" />
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
У меня создалось впечатление, что при динамическом создании объектов в коде нужно также воссоздать их при каждом обратном обращении, это неверно? – enr4ged
Нет! Не верно. В этом весь смысл ViewState. Вы создаете их один раз, когда страница загружается. Затем они сохраняются в ViewState через обратную передачу. Доверьтесь мне. Поместите это If-Then на место и посмотрите, что произойдет. Вы будете довольны результатами. Каждый метод Page_Load() на КАЖДОЙ странице должен иметь это If-Then. КАЖДЫЙ ВРЕМЯ :-) –
Когда я изменяю его, чтобы включить If Not IsPostback - таблица остается пустой после каждой обратной передачи. – enr4ged