Solved

Using ASP.Net 2005 (VB), how can I retain changes made to data in dynamically-created html table on postback?

Posted on 2012-03-12
13
609 Views
Last Modified: 2012-03-14
The table is populated using a stored-procedure.  A checkbox and textbox are dynamically added to each row to accommodate user-input.  The table displays properly on the form, accepts and retains input, but I am unable to process changes made by the user to the checkbox and/or textbox because they are not retained in the table object on postback.

Please provide best-practice solution for retaining changes to the content of controls which were dynamically added to rows in a table on postback.  I'm relatively new to ASP.Net, coming over from years of Desktop development, so let me know if I have failed to properly word my question, and I'll try to elaborate.

Thanks!
0
Comment
Question by:ggoodlett
  • 7
  • 6
13 Comments
 
LVL 9

Expert Comment

by:lojk
ID: 37714275
Hi - i know how this feels. Winforms development has persistence baked-in but it can take a bit more effort in ASP.

Heres a couple of tricks..

Use Page.IsPostback to work out if its time to initialize or reload from SessionState/DB

        protected void Page_Load(object sender, EventArgs e)
        {

            if (!IsPostBack)
            {
                SetCalendar(DateTime.Now.AddMonths(-1));
            //only sets the calendar to intial value on 'first view'
            }
        }

Persist your objects in a session variable - not always the most efficient solution (i.e. pushing it back to a DB backing store is a bit more reliable) - here is a neat way of doing it that as a OldWinformsBoy I find convenient and familiar...

(this stores an Int but a datatable or any other class instance works too)

        public int StudentID
        {
            get
            {
                string tName = Page.Title.ToString() + "StudentID";
                try
                {
                  return Convert.ToInt32(HttpContext.Current.Session[tName].ToString());
                }
                catch (Exception)
                {
                    return 0;
                }
            }
            set
            {
                string tName = Page.Title.ToString() + "StudentID";
                HttpContext.Current.Session[tName] = value;
            }
        }

Dont panic! - I have taken the liberty of converting this to VB (please forgive any minor error) for you using..

http://www.developerfusion.com/tools/convert/csharp-to-vb/

Protected Sub Page_Load(sender As Object, e As EventArgs)

      If Not IsPostBack Then
            'only sets the calendar to intial value on 'first view'
            SetCalendar(DateTime.Now.AddMonths(-1))
      End If
End Sub

Public Property StudentID As Integer
      Get
            Dim tName As String = Page.Title.ToString() & "StudentID"
            Try
            Return Convert.ToInt32(HttpContext.Current.Session(tName).ToString())
            Catch generatedExceptionName As Exception
                  Return 0
            End Try
      End Get
      Set
            Dim tName As String = Page.Title.ToString() & "StudentID"
            HttpContext.Current.Session(tName) = value
      End Set
End Property

Hope that helps
0
 
LVL 9

Expert Comment

by:lojk
ID: 37714292
Sorry - forgot to say, also ensure that you set EnableViewState=True on any page/control you are using too.
0
 

Author Comment

by:ggoodlett
ID: 37715280
Hey lojk,

Thanks for responding.  I was beginning to think that I was the only one out here that didn't get this stuff.  Forgive my ignorance, but I'm still not sure how to go about storing data from user input that may involve many rows at the same time.  I see how you are passing the contents of a single control into a session variable, but how would I do that for 50 rows at once?  Also, how do I reference the dynamically-added control for retrieving it's value?  I haven't found a way to handle a TextChanged event.

Thanks for your help!!
0
 
LVL 9

Expert Comment

by:lojk
ID: 37715769
Unfortuntely the one thing i cant do is tell you how to do this as your question has massive scope (and i think you have already gone down the wrong path from what you are saying) and i dont know what else you know about other things like SQL Server/XML/Winforms Visual Databinding blah blah. Dynamically creating controls in ASP.Net is not as easy (to manage) as it is in Winforms, nor is it particularly encouraged or required and is definitely not for the faint hearted.

I can tell you that ASP.Net gives you as a winforms guy the opportunity to continuing thinking that way (i.e. not as a web developer) - I was only saying to somebody today how i have never actually written one line of html or javascript in my life (but i have done loads of websites)! Also remember that ASP.Net is not ASP (classic) and dont be fooled into thinking you can apply the same methodologies from that as you can here.

In visual studio do a file new project - and choose new Web Application (or Website depending on the version you have). If you dont have Visual Studio you can get the express editions for free (well no money anyway).

Getting Started: ASP.Net Overview
http://msdn.microsoft.com/en-us/library/ee532866.aspx

50 rows of data is just a datatable - a group of tables is called a dataset. You can design a dataset to hold your data and bind that dataset to a gridview on a webform(aspx) and it will work quite like you expect it to. (You can then store that dataset in a session variable property as per my example).

Creating typed datasets:
http://msdn.microsoft.com/en-us/library/04y282hb(v=vs.80).aspx

for your test scenario an access database might be a better place to start as a temporary store for the data and bind that to your data.

Binding Data to controls in ASP.Net
http://msdn.microsoft.com/en-us/library/ms178359.aspx

Here is the MSDN page for using ASP Gridview control
http://msdn.microsoft.com/en-us/library/dd548005.aspx

As you can see, you have got a bit of reading to do. It took me quite a while to get my head around ASP.Net but once you have the basics it gets easier and easier.  There are no shortcuts here though i'm afraid, you just have to learn how to use it - like you did with winforms.

An ASP.Net page is sort of like a windows form and for all intents and purposes works the same way, just that each event causes a 'postback' (the whole thing gets sent back to the server and operated on and the result comes back as a whole new page) - your code only effectively runs (i.e. can be breakpointed) during that postback phase (while the browser is 'loading') unless you use a bunch of javascript on the client (which is definitely beyond the scope of this question).

As for the question how do i handle a 'textchanged' event - it is simliar. If the Textbox has its 'AutoPostBack' property set to true, whenever it is changed at the browser, the browser posts the whole page back and at that point you get the chance to operate on its value again. Rather than issuing a post back after every UI operation it is better to have a submit button (that actually implicitly postsback) and during that time you can validate the textboxes or Gridview/Underlying data store before returning the change of UI state to the browser.
0
 

Author Comment

by:ggoodlett
ID: 37716091
Thanks for the additional info.  You are quite correct in that things which are sooo easy in Winforms are anything but in ASP.Net.  I've been battling this issue for several days, and I'm having a hard time finding information on how other developers have handled similar problems.

I am quite experienced in databases and datatables/sets, etc.  I've been doing this stuff for over 20 years - going back to, well, GWBASIC on the PC and COBOL on other platforms - long before OOP ever came into existence.  I've come to the conclusion, however, that all of that old experience hurts more than it helps, anymore.

In this case I am passing the results of execution of a stored-proc containing a SELECT statement into a datatable.  I'm not binding the datatable to the html table, rather I am processing each individual row of the datatable into the html table, adding cells for a checkbox and textbox to each row as it is added to the table.  All of that works perfectly, displays perfectly on the form and accepts user-input.

The entire problem is around capturing and processing that user-input.  If I could raise an event or trap the change to a checkbox or textbox in the table, I could capture those values and write them to a session variable or even to an array, but I haven't been able to find a way to do that.  I know how to handle the TextChanged event and AutoPostBack property for a control on the page, but I don't see properties or event-handlers for dynamically added controls.  Am I missing something there?

In the beginning, this seemed like the best approach for capturing user selection of a site record and associating the number of installations for that site at the same time.  I may have to opt for a two-step process by first using a checkboxlist for site-selection, then have the users add the number of installs for each selected-site in a second step.  I know how to do that, but the users won't like having to do it in two steps.

Can you offer a suggestion for your idea of the best way to handle displaying a list of records from a table, allow user-selection of one or more records from that list, capturing additional info from the user for each selected record and ultimately writing all of that back out to the database?

Thanks again for your help - and your patience.
0
 
LVL 9

Accepted Solution

by:
lojk earned 500 total points
ID: 37716327
OK, Cool - apologies if some of the previous post was 'sucking eggs' in places - always hard to gauge user ability from one post ;-)

I would still recommend reviewing the options of visual databinding as you could add a GridView bound to a SQLDataSource and using the DataSource wizard specify the spGet as the 'Select' and assuming the rest of the CRUD operations are also SPs bind them in too to the Insert/Update/Delete operations - this approach also gives the ability to bind more than one Control to that dataset providing an easy way to implement a 'Selected Item Details Panel' that you crave (please see original comment for more details on using Databinding in ASP.Net). For me, i find it much easier to bind straight to tables/select statements but i understand thats not always an option.

If you decide to persist, and that is still quite a valid choice you just need to add those handlers yourself when you dynamically create and add the control.

I guess you do something like this... (it's not easy to quickly setup a replica here and I am more C# these days than VB so pseudo code only and apologies again for minor errors).

private sub WriteTable()
response.write("<table>")
For rowindex = 0 to MyDataTable.Rows
response.write("<tr>")
response.write("<td>")
dim ThisRowsUserName as Textbox = new TextBox()
ThisRowsUsername.name= "UserName" + rowindex
ThisRowsUsername.Text= MyDataTable.Rows(rowindex)["username"].tostring ()
response.write("</td>")
''more columns
response.write("</tr>")
end for

response.write("</table>")
end Sub


something like this is what you need

private sub WriteTable()
response.write("<table>")
For rowindex = 0 to MyDataTable.Rows
response.write("<tr>")
response.write("<td>")
dim ThisRowsUserName as Textbox = new TextBox()
ThisRowsUsername.name= "UserName" + rowindex
ThisRowsUsername.Text= MyDataTable.Rows(rowindex)["username"].tostring ()
ThisRowsUserName.TextChanged += AddressOf(HandleUserNameChange())
response.write("</td>")
''more columns
response.write("</tr>")
end for

private sub HandleUserNameChange(sender , eventargs)  
'sorry that really is the best i can do - ultimately it should have the same signature as a normal static textbox changed event

dim ChangedTextBox as Textbox = directcast(sender,textbox)
dim RowIndex as int = convert.int( ChangedTextbox.Name.replace("Username","")) '' and i am sure you can come up with a cleaner way of doing this

My.DataTableThatIsStoredInTheSessionVariable.Rows(Rowindex)["username"] = ChangedTextBox.Text

End sub

as i said, it all gets quite sticky and horrible quite quickly as you add many more columns but this should be close and will work (once you weedle the bugs out of what i have given you :-S ) but please at least consider using VisualDataBinding - it's much easier once you are familiar with it and the tooling in VS (even 2005) is pretty good as is it's support for SQL-SPs.
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 

Author Comment

by:ggoodlett
ID: 37716695
No apologies necessary, my friend.  This stuff has a way of causing an old-timer like me to lose all confidence in his ability, especially after spending days hammering on something that would take five minutes in a Desktop app.

Okay, let me take your suggestions and see what I can come up with.  I looked at the GridView before going with the table-approach, but I didn't think that it was going to do what I needed.  I may take another look at it, and I may look at building event_handlers for the dynamic controls.  I'd like to keep this question open for now, if that's alright.  I may have (and probably will have) a follow-up question or two.

Thanks for your help and your patience.
0
 
LVL 9

Expert Comment

by:lojk
ID: 37717413
That's fine I'll be off the grid for a few days, going away for the rest of the week and most of the weekend - I'll be monitoring but not able to do longer replys.
Mull it over, suggest you do a (seperate) test project and let me know how you get on. if I get chance I'll try and find some better examples (than me hand-hacking my non-native language in a text editor) for you too.
0
 

Author Comment

by:ggoodlett
ID: 37717827
lojk,

You are the man!  I opted for the GridView approach and have it working like a charm.  Thank you for shoving me in that direction!

Really appreciate your help on this.  Hope you have a great trip!
0
 
LVL 9

Expert Comment

by:lojk
ID: 37718046
The best way to describe visual databinding and its tooling (in winforms and asp.net ) is like the relationship you have with your sat-nav. The first time you use it you feel like you wanna reach in the back seat for the trusty map but once you know how it can be used and learn to trust it you start using it even for a trip to the shops. Yeah, it doesn't always make sense to use it but mostly it helps - you'll know when it won't the more times you use it. (ok, pretty tenous but you get my point)

To pick up on your point from earlier, I been doing this 15+ years too and i have found the old knowledge doesn't help much at all - I have learned more in the last few years by trusting ms tools and wizards to do the heavy lifting for me more and more which frees up spare head-space to learn all the new stuff that they keep drip feeding us with; this improves my productivity/output which ultimately just allows me to do a better job in less time and the less code you have to write, the easier it is for you and others to maintain what you have done.

Glad I saved you (at least) a few days work - always nice when someone can benefit from my blood and tears :-)
0
 

Author Comment

by:ggoodlett
ID: 37720658
You're right.  That's a great analogy.

What I wound up doing was binding the GridView to the datatable which was populated from the stored-proc.  In this app, I am not at liberty to bind form-objects directly to objects in the database, and I actually prefer to keep my data-layer isolated from the user-interface.  I believe that this makes the code easier to manage.  I added a couple of template-fields to the GridView to contain the checkbox and textbox and set auto-postback to true.  That allowed me to capture the changes and write them back to the db.  I did in a GridView in an hour and a half what I had wasted about five days trying to figure out how to do with a table.  Won't make that mistake again.

I find myself using the wizards more and more, too.  One can usually tweak the results to get exactly what they need, saving time and keystrokes in the process.

Thanks again for the help, and have a great vacation!
0
 
LVL 9

Expert Comment

by:lojk
ID: 37721020
Good man - if only i was able to keep my mucky business logic fingers that far away from my data layers ;-)


One last tip... a 'bonus' so to speak...

The only problem with (auto)postback in ASP.Net is the horrible page flash and reset during postback response - if you were using asp.net 4.0  you could surround that grid and its datasource in an update panel. Bang - Partial Page PostBacks / Web2.0 in a box!

If your wallet wont stretch to a copy of VS2010 though you can install the earlier version of the Ajax Extensions for 2005 - heres the link..

http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=883

although that might be one to play with, not in your production code, while I'm on holiday ;-)
0
 

Author Comment

by:ggoodlett
ID: 37721154
Yeah buddy, I hate that disgusting flash and reset, too.  Had decided that it was inevitable.

Thanks for the link.  I'll look into the Ajax extensions when time permits.  I'm under the gun to get finished with this app - especially after losing a week dinking around with html tables.  I'll also see if I can't get my employer to spring for a copy of VS 2010, but I'm not holding my breath.

Thanks for the tip!
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

AJAX ModalPopupExtender has a required property "TargetControlID" which may seem to be very confusing to new users. It means the server control that will be extended by the ModalPopup, for instance, if when you click a button, a ModalPopup displays,…
Just a quick little trick I learned recently.  Now that I'm using jQuery with abandon in my asp.net applications, I have grown tired of the following syntax:      (CODE) I suppose it just offends my sense of decency to put inline VBScript on a…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now