views:

471

answers:

5

I have the following situation:

A user will define a certain filter on a page, and on postback I will query the database using that filter and return a bunch of matching records to the user, each with a checkbox next to it, so he can choose whether to act on each of those records.

In Classic ASP / PHP I can generate a lot of controls named "chk__*" and then on postback go through all the $POST entries looking for the ones prefixed "chk".

What is the best way to do this in ASP.Net 2.0?

I can do it easily by implementing a Repeater with a Template containing the checkbox, bind the Repeater to a Dataset, and then on the second Postback, I just do:

For Each it As RepeaterItem In repContacts.Items
    Dim chkTemp As CheckBox = DirectCast(it.FindControl("cbSelect"), CheckBox)
    If chkTemp.Checked Then

    End If
Next

However this has the slight disadvantage of giving me a HUGE Viewstate, which is really bad because the client will need to re-upload the whole viewstate to the server, and these people will probably be using my site over a crappy connection.

Any other ideas? (I can also create the controls dynamically and iterate through Request.Form as in the old days, however, I was looking for a cleaner

A: 

Disable the ViewState. In case it cannot be done try using Session to store the view state

Ramesh
The only way I can disable the Viewstate is if I regenerate the control tree before the Page_Load event (so, on Page_Init).But at that point I can't read the data for the filter controls to re-query the DB (not cleanly at least).
Daniel Magliola
As for storing Viewstate somewhere else, that seems to be more work than it's worth it for this, honestly...Thanks for the ideas!
Daniel Magliola
Data for filter controls is not present in a text box or some thing on the page, whose values will be retained by a post back?
Ramesh
@Ramesh: Yes, they will, but those are not loaded into the control's values at the time Page_Init runs. And I need to repopulate controls before Page_Load, otherwise, "which controls were checked" won't be loaded by ASP.Net
Daniel Magliola
+2  A: 

I recommend the classic ASP solution when faced with absurd Viewstate conditions. It is sad to lose the nice features it provides, but combining some Viewstate enabled controls (asp:*) with some classic techniques (input type="...") has saved me a lot of headaches in the past.

Sometimes you just want to do something simple, and the simple solution beats "WYSIWYG" form editing.

Godeke
+3  A: 

Do it the same way you did it in classic ASP. Use <input type="checkbox"> instead of <asp:checkbox>. You can access the raw post paramaters using Request.Form

Josh Hinman
That's a good idea (generating <input> directly, to avoid weird naming). I'll try this and CheckboxList control, and see which one is better (i'm assuming checkboxlist control will use viewstate too) Thanks!
Daniel Magliola
+5  A: 

Have you looked at the CheckBoxList control? You can bind it to your data set, provide text member and value member items, and it will also allow you to easily see which items are checked. There is also the ability to dynamically add more checkbox items if needed.

Dillie-O
I'll check it out, and if it doesn't work, i'll go with Josh's solution.Thanks all!
Daniel Magliola
+2  A: 

One of the things that I have done is to record the state of a check via AJAX in the session, then on Postback (full or partial via AJAX), look in the session for the items to perform the selected action on.

The basic idea is to add an onclick handler to the checkbox that knows the id of the associated item. In the on click handler communicate this id back to the server via AJAX and record it in the session -- you'll need to communicate checkbox status as well so you can uncheck items. Have the handler for the submit control use the data about which items were selected from the session.

This way allows you to handle paged data as well, since you can set the initial value of the checkbox from the session when rendering (either full or partial) a page with checked items on it.

It might look something like this. Assuming ASP.NET AJAX with PageMethods (and ScriptManager, of course).

<script type='text/javascript'>
   function record(checkbox,item)
   {
       var context = { ctl : checkbox };
       PageMethods.Record(item,checkbox.checked,onSuccess,onFailure,context);
   }

   function onSuccess(result,context)
   {
      // do something, maybe highlight the row, maybe nothing
   }

   function onFailure(error,context)
   {
       context.ctl.checked = false;
       alert(error.get_Message());
   }
</script>


...
<tr><td><input type='checkbox' onclick='record(this,"item_1");'></td><td>Item 1</td></tr>
...

Codebehind

[WebMethod(EnableSessionState=true)]
public static void Record( string itemName, bool value )
{
     List<string> itemList = (List<string>)Session["Items"];
     if (itemList == null)
     {
        itemList = new List<string>();
        Session["Items"] = itemList;
     }
     if (itemList.Contains(itemName) && !value)
     {
         itemList.Remove(itemName);
     }
     else if (!itemList.Contains(itemName) && value)
     {
         itemList.Add(itemName);
     }       
}

protected void button_OnClick( object sender, EventArgs e )
{
     List<string> itemList = (List<string>)Session["Items"];
     if (itemList != null)
     {
         foreach (string item in itemList)
         {
             // do something with the selected item
         }
     }
}
tvanfosson
Thanks for the idea!I will end up manually outputting the <input>s "ASP Classic style", because it's the easiest path, but this is a good idea to keep in mind for the future, I would've never thought of that. Thanks!
Daniel Magliola