![]() |
|
|
|||||||
![]() |
ASP Net - View State issue with dynamically added controls-Plz help :-) |
|
|
Thread Tools | Search this Thread |
|
|
#1 |
|
I have a problem that I am desperate to understand.
It involves dynamically adding controls to a Table control that is built as a result of performing a database query. I am not looking to avoid the problem by avoiding the table control or resorting to databound controls that better manage state for me. I hope to understand how to solve the problem by using the Table web control and sticking to the approach of building the table at run time rather than using databound controls. I tried to create the shortest code example that, when run, illustrates the problem. This is basically what I want to do: 1) I want to query a table, Table1, which has two columns, "KeyCol" (PK int) and "Hide" (bit). 2) I want to return all the rows where the Hide flag is not set to 1. 3) For each returned row, I want to use the Table control to dynamically add a row to the Table for each record returned by the above query. 4) For each TableRow created, I will add 2 TableCells (columns). The first column wil be display the KeyCol value returned. 5) In the 2nd column, I will display a blank text box. 6) If the user type ANY text in the text box and pushes the BUTTON at the bottom of the page, this will update the HIDE flag for the selected record in Table1. 7) The display will then be refreshed. Since the query excludes recs where the Hide flag is set, this record will be removed from the table after the refresh, Now the problem.... Everything works fine up to this point. But the next time that the user enters text in one of the remaining textboxes and pushes the BUTTON, the logic does not detect that there is any text in the text box! Howver, on the NEXT submit, the value will be detected! This is my understanding: In order to determine if a value was typed in the text box since the last submit, the table must be REBUILT each time. However, if the TABLE is redrawn (all rows removed and rebuilt), I think the view state is getting out of sync somehow (not sure!). I assume that the answer to this problem is just a tweek somewhere. Can someone help. I've spend too many hours on what should be a basic problem. Below is everything you should need to have a running example of what I am doing. I would be greatly appreciative to any help. Thanks ------------------------------------------------------------------------------------------------------------------ CREATE TABLE [dbo].[Table1] ( [KeyCol] [int] NOT NULL IDENTITY(1, 1), [Hide] [bit] NOT NULL ) GO -- Constraints and indexes ALTER TABLE [dbo].[Table1] ADD CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED ([KeyCol]) GO BEGIN TRANSACTION SET IDENTITY_INSERT [dbo].[Table1] ON INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (1, 0) INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (2, 0) INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (3, 0) INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (4, 0) INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (5, 0) INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (6, 0) INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (7, 0) SET IDENTITY_INSERT [dbo].[Table1] OFF COMMIT TRANSACTION ----------------------------------------------------------------------------- Imports System.Web.UI.WebControls Imports System.Data.SqlClient Public Class WebForm1 Inherits System.Web.UI.Page #Region " Web Form Designer Generated Code " 'This call is required by the Web Form Designer. <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() End Sub Protected WithEvents Button1 As System.Web.UI.WebControls.Button Protected WithEvents Table1 As System.Web.UI.WebControls.Table 'NOTE: The following placeholder declaration is required by the Web Form Designer. 'Do not delete or move it. Private designerPlaceholderDeclaration As System.Object Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init 'CODEGEN: This method call is required by the Web Form Designer 'Do not modify it using the code editor. InitializeComponent() End Sub #End Region Dim SqlConnection As SqlConnection Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load SqlConnection = New SqlConnection("server=(local);database=skpireposit ory;uid=skpiuser;pwd=skpiuser") SqlConnection.Open() BuildTable() End Sub Private Sub BuildTable() Dim TableRow As TableRow Dim TableCell As TableCell Dim TextBox As TextBox Dim ds As New DataSet Dim DataRow As DataRow Dim SqlDataAdapter As New SqlDataAdapter("Select * from table1 where Hide <> 1", SqlConnection) SqlDataAdapter.Fill(ds, "table1") For Each DataRow In ds.Tables(0).Rows 'Add Row TableRow = New TableRow Table1.Rows.Add(TableRow) 'Add 1st Col Cell TableCell = New TableCell TableCell.Text = DataRow.Item("KeyCol").ToString TableRow.Cells.Add(TableCell) 'Add 2nd Col TextBox TableCell = New TableCell TableRow.Cells.Add(TableCell) TextBox = New TextBox TableCell.Controls.Add(TextBox) Table1.Rows.Add(TableRow) Next End Sub Private Sub ClearRows() Dim r As Integer For r = Table1.Rows.Count - 1 To 0 Step -1 Table1.Rows.Remove(Table1.Rows.Item(r)) Next End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim TableRow As TableRow Dim TextBox As TextBox Dim KeyCol As Integer Dim RefreshTable As Boolean = False For Each TableRow In Table1.Rows KeyCol = CType(TableRow.Cells(0).Text, Integer) TextBox = CType(TableRow.Cells(1).Controls(0), TextBox) If Trim(TextBox.Text) <> "" Then Dim SqlCommand As New SqlCommand("UPDATE Table1 SET Hide = 1 WHERE KeyCol = " & KeyCol.ToString, SqlConnection) SqlCommand.ExecuteNonQuery() RefreshTable = True End If Next If RefreshTable Then ClearRows() BuildTable() End If End Sub End Class ---------------------------------------------------------------------------------------------------------- <%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" Inherits="WebApplication2.WebForm1"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <title>WebForm1</title> <meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR"> <meta content="Visual Basic .NET 7.1" name="CODE_LANGUAGE"> <meta content="JavaScript" name="vs_defaultClientScript"> <meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema"> </HEAD> <body> <form id="Form1" method="post" runat="server"> <asp:table id="Table1" runat="server"></asp:table> <asp:button id="Button1" runat="server" Text="Type anything in the text box to remove that row"></asp:button></form> </body> </HTML> Chad |
|
|
|
|
#2 |
|
Posts: n/a
|
I think I got the answer!
I think I have the answer! Someone correct me if there is more to it than this: It appears that if I use assign an ID to the dynamically created controls, and reuse the same ID when I rebuild the controls, the ViewState syncs up! "Chad" <> wrote in message news:ctf1dd$s4j$... I have a problem that I am desperate to understand. It involves dynamically adding controls to a Table control that is built as a result of performing a database query. I am not looking to avoid the problem by avoiding the table control or resorting to databound controls that better manage state for me. I hope to understand how to solve the problem by using the Table web control and sticking to the approach of building the table at run time rather than using databound controls. I tried to create the shortest code example that, when run, illustrates the problem. This is basically what I want to do: 1) I want to query a table, Table1, which has two columns, "KeyCol" (PK int) and "Hide" (bit). 2) I want to return all the rows where the Hide flag is not set to 1. 3) For each returned row, I want to use the Table control to dynamically add a row to the Table for each record returned by the above query. 4) For each TableRow created, I will add 2 TableCells (columns). The first column wil be display the KeyCol value returned. 5) In the 2nd column, I will display a blank text box. 6) If the user type ANY text in the text box and pushes the BUTTON at the bottom of the page, this will update the HIDE flag for the selected record in Table1. 7) The display will then be refreshed. Since the query excludes recs where the Hide flag is set, this record will be removed from the table after the refresh, Now the problem.... Everything works fine up to this point. But the next time that the user enters text in one of the remaining textboxes and pushes the BUTTON, the logic does not detect that there is any text in the text box! Howver, on the NEXT submit, the value will be detected! This is my understanding: In order to determine if a value was typed in the text box since the last submit, the table must be REBUILT each time. However, if the TABLE is redrawn (all rows removed and rebuilt), I think the view state is getting out of sync somehow (not sure!). I assume that the answer to this problem is just a tweek somewhere. Can someone help. I've spend too many hours on what should be a basic problem. Below is everything you should need to have a running example of what I am doing. I would be greatly appreciative to any help. Thanks ------------------------------------------------------------------------------------------------------------------ CREATE TABLE [dbo].[Table1] ( [KeyCol] [int] NOT NULL IDENTITY(1, 1), [Hide] [bit] NOT NULL ) GO -- Constraints and indexes ALTER TABLE [dbo].[Table1] ADD CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED ([KeyCol]) GO BEGIN TRANSACTION SET IDENTITY_INSERT [dbo].[Table1] ON INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (1, 0) INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (2, 0) INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (3, 0) INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (4, 0) INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (5, 0) INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (6, 0) INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (7, 0) SET IDENTITY_INSERT [dbo].[Table1] OFF COMMIT TRANSACTION ----------------------------------------------------------------------------- Imports System.Web.UI.WebControls Imports System.Data.SqlClient Public Class WebForm1 Inherits System.Web.UI.Page #Region " Web Form Designer Generated Code " 'This call is required by the Web Form Designer. <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() End Sub Protected WithEvents Button1 As System.Web.UI.WebControls.Button Protected WithEvents Table1 As System.Web.UI.WebControls.Table 'NOTE: The following placeholder declaration is required by the Web Form Designer. 'Do not delete or move it. Private designerPlaceholderDeclaration As System.Object Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init 'CODEGEN: This method call is required by the Web Form Designer 'Do not modify it using the code editor. InitializeComponent() End Sub #End Region Dim SqlConnection As SqlConnection Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load SqlConnection = New SqlConnection("server=(local);database=skpireposit ory;uid=skpiuser;pwd=skpiuser") SqlConnection.Open() BuildTable() End Sub Private Sub BuildTable() Dim TableRow As TableRow Dim TableCell As TableCell Dim TextBox As TextBox Dim ds As New DataSet Dim DataRow As DataRow Dim SqlDataAdapter As New SqlDataAdapter("Select * from table1 where Hide <> 1", SqlConnection) SqlDataAdapter.Fill(ds, "table1") For Each DataRow In ds.Tables(0).Rows 'Add Row TableRow = New TableRow Table1.Rows.Add(TableRow) 'Add 1st Col Cell TableCell = New TableCell TableCell.Text = DataRow.Item("KeyCol").ToString TableRow.Cells.Add(TableCell) 'Add 2nd Col TextBox TableCell = New TableCell TableRow.Cells.Add(TableCell) TextBox = New TextBox TableCell.Controls.Add(TextBox) Table1.Rows.Add(TableRow) Next End Sub Private Sub ClearRows() Dim r As Integer For r = Table1.Rows.Count - 1 To 0 Step -1 Table1.Rows.Remove(Table1.Rows.Item(r)) Next End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim TableRow As TableRow Dim TextBox As TextBox Dim KeyCol As Integer Dim RefreshTable As Boolean = False For Each TableRow In Table1.Rows KeyCol = CType(TableRow.Cells(0).Text, Integer) TextBox = CType(TableRow.Cells(1).Controls(0), TextBox) If Trim(TextBox.Text) <> "" Then Dim SqlCommand As New SqlCommand("UPDATE Table1 SET Hide = 1 WHERE KeyCol = " & KeyCol.ToString, SqlConnection) SqlCommand.ExecuteNonQuery() RefreshTable = True End If Next If RefreshTable Then ClearRows() BuildTable() End If End Sub End Class ---------------------------------------------------------------------------------------------------------- <%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" Inherits="WebApplication2.WebForm1"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <title>WebForm1</title> <meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR"> <meta content="Visual Basic .NET 7.1" name="CODE_LANGUAGE"> <meta content="JavaScript" name="vs_defaultClientScript"> <meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema"> </HEAD> <body> <form id="Form1" method="post" runat="server"> <asp:table id="Table1" runat="server"></asp:table> <asp:button id="Button1" runat="server" Text="Type anything in the text box to remove that row"></asp:button></form> </body> </HTML> |
|
|
|
#3 |
|
Posts: n/a
|
Chad:
I didn't look at your question in any great detail..but what your saying makes a lot of sense...viewstate works by matching things in the Request.Form collection to controls based on their ID value...so if you aren't re-creating the controls with the right ID, then you'd likely see problems I realize you've solved your problem, but you might wanna take a look at: http://www.denisbauer.com/ASPNETCont...aceholder.aspx which is a free control which aids in maintaining viewstate for dynamically created controls. Cheers, Karl -- MY ASP.Net tutorials http://www.openmymind.net/ "Chad" <> wrote in message news:ctf665$3m$... I think I got the answer! I think I have the answer! Someone correct me if there is more to it than this: It appears that if I use assign an ID to the dynamically created controls, and reuse the same ID when I rebuild the controls, the ViewState syncs up! "Chad" <> wrote in message news:ctf1dd$s4j$... I have a problem that I am desperate to understand. It involves dynamically adding controls to a Table control that is built as a result of performing a database query. I am not looking to avoid the problem by avoiding the table control or resorting to databound controls that better manage state for me. I hope to understand how to solve the problem by using the Table web control and sticking to the approach of building the table at run time rather than using databound controls. I tried to create the shortest code example that, when run, illustrates the problem. This is basically what I want to do: 1) I want to query a table, Table1, which has two columns, "KeyCol" (PK int) and "Hide" (bit). 2) I want to return all the rows where the Hide flag is not set to 1. 3) For each returned row, I want to use the Table control to dynamically add a row to the Table for each record returned by the above query. 4) For each TableRow created, I will add 2 TableCells (columns). The first column wil be display the KeyCol value returned. 5) In the 2nd column, I will display a blank text box. 6) If the user type ANY text in the text box and pushes the BUTTON at the bottom of the page, this will update the HIDE flag for the selected record in Table1. 7) The display will then be refreshed. Since the query excludes recs where the Hide flag is set, this record will be removed from the table after the refresh, Now the problem.... Everything works fine up to this point. But the next time that the user enters text in one of the remaining textboxes and pushes the BUTTON, the logic does not detect that there is any text in the text box! Howver, on the NEXT submit, the value will be detected! This is my understanding: In order to determine if a value was typed in the text box since the last submit, the table must be REBUILT each time. However, if the TABLE is redrawn (all rows removed and rebuilt), I think the view state is getting out of sync somehow (not sure!). I assume that the answer to this problem is just a tweek somewhere. Can someone help. I've spend too many hours on what should be a basic problem. Below is everything you should need to have a running example of what I am doing. I would be greatly appreciative to any help. Thanks ------------------------------------------------------------------------------------------------------------------ CREATE TABLE [dbo].[Table1] ( [KeyCol] [int] NOT NULL IDENTITY(1, 1), [Hide] [bit] NOT NULL ) GO -- Constraints and indexes ALTER TABLE [dbo].[Table1] ADD CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED ([KeyCol]) GO BEGIN TRANSACTION SET IDENTITY_INSERT [dbo].[Table1] ON INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (1, 0) INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (2, 0) INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (3, 0) INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (4, 0) INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (5, 0) INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (6, 0) INSERT INTO [dbo].[Table1] ([KeyCol], [Hide]) VALUES (7, 0) SET IDENTITY_INSERT [dbo].[Table1] OFF COMMIT TRANSACTION ----------------------------------------------------------------------------- Imports System.Web.UI.WebControls Imports System.Data.SqlClient Public Class WebForm1 Inherits System.Web.UI.Page #Region " Web Form Designer Generated Code " 'This call is required by the Web Form Designer. <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent() End Sub Protected WithEvents Button1 As System.Web.UI.WebControls.Button Protected WithEvents Table1 As System.Web.UI.WebControls.Table 'NOTE: The following placeholder declaration is required by the Web Form Designer. 'Do not delete or move it. Private designerPlaceholderDeclaration As System.Object Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init 'CODEGEN: This method call is required by the Web Form Designer 'Do not modify it using the code editor. InitializeComponent() End Sub #End Region Dim SqlConnection As SqlConnection Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load SqlConnection = New SqlConnection("server=(local);database=skpireposit ory;uid=skpiuser;pwd=skpiuser") SqlConnection.Open() BuildTable() End Sub Private Sub BuildTable() Dim TableRow As TableRow Dim TableCell As TableCell Dim TextBox As TextBox Dim ds As New DataSet Dim DataRow As DataRow Dim SqlDataAdapter As New SqlDataAdapter("Select * from table1 where Hide <> 1", SqlConnection) SqlDataAdapter.Fill(ds, "table1") For Each DataRow In ds.Tables(0).Rows 'Add Row TableRow = New TableRow Table1.Rows.Add(TableRow) 'Add 1st Col Cell TableCell = New TableCell TableCell.Text = DataRow.Item("KeyCol").ToString TableRow.Cells.Add(TableCell) 'Add 2nd Col TextBox TableCell = New TableCell TableRow.Cells.Add(TableCell) TextBox = New TextBox TableCell.Controls.Add(TextBox) Table1.Rows.Add(TableRow) Next End Sub Private Sub ClearRows() Dim r As Integer For r = Table1.Rows.Count - 1 To 0 Step -1 Table1.Rows.Remove(Table1.Rows.Item(r)) Next End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim TableRow As TableRow Dim TextBox As TextBox Dim KeyCol As Integer Dim RefreshTable As Boolean = False For Each TableRow In Table1.Rows KeyCol = CType(TableRow.Cells(0).Text, Integer) TextBox = CType(TableRow.Cells(1).Controls(0), TextBox) If Trim(TextBox.Text) <> "" Then Dim SqlCommand As New SqlCommand("UPDATE Table1 SET Hide = 1 WHERE KeyCol = " & KeyCol.ToString, SqlConnection) SqlCommand.ExecuteNonQuery() RefreshTable = True End If Next If RefreshTable Then ClearRows() BuildTable() End If End Sub End Class ---------------------------------------------------------------------------------------------------------- <%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" Inherits="WebApplication2.WebForm1"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <title>WebForm1</title> <meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR"> <meta content="Visual Basic .NET 7.1" name="CODE_LANGUAGE"> <meta content="JavaScript" name="vs_defaultClientScript"> <meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema"> </HEAD> <body> <form id="Form1" method="post" runat="server"> <asp:table id="Table1" runat="server"></asp:table> <asp:button id="Button1" runat="server" Text="Type anything in the text box to remove that row"></asp:button></form> </body> </HTML> |
|