views:

1227

answers:

3

Consider the current algorithm below that iterates through a GridView's rows to find whether the contained Checkbox is selected/checked.

List<int> checkedIDs = new List<int>();

foreach (GridViewRow msgRow in messagesGrid.Rows)
{
  CheckBox chk = (CheckBox)msgRow.FindControl("chkUpdateStatus");
  if (chk.Checked){
   //we want the GridViewRow's DataKey value
   checkedMsgIDs.Add(int.Parse(messagesGrid.DataKeys[msgRow.RowIndex].Value.ToString()));
  }
}

This works as expected: you're left with a fully populated List<int>.

Question: How would you or could you re-write or improve this algorithm using LINQ to search the GridView for all the rows who have their Checkbox selected/checked?

+5  A: 

I'm pretty sure you're not going to get any performance improvement from this, but it might make it slightly easier to read:

var checkedIDs = from GridViewRow msgRow in messagesGrid.Rows
                 where ((CheckBox)msgRow.FindControl("chkUpdateStatus")).Checked
                 select Int32.Parse(messagesGrid.DataKeys[msgRow.RowIndex].Value.ToString());

Again, not sure it makes a difference. Also, why are you converting to a string then to an int? Is there something Convert.ToInt32 can't do for you?

lc
Thanks LC! `Convert.ToInt32` should work fine. Thanks for that enhancement as well!
p.campbell
+5  A: 

I am not sure if Rows is IEnumerable they may not be, but I am going to assume they are

List<int> checkedIDs = messagesGrid.Rows
  .Where<GridViewRow>(i => (CheckBox)i.FindControl("chkUpdateStatus").Checked)
  .Select<GridViewRow, int>(i => return int.Parse(messagesGrid.DataKeys[i.RowIndex].Value.ToString()))
  .ToList<int>();

I just did this in notepad, there might be a compile error in there. But this is how you could do the same thing with Linq.

David Basarab
Yeah, looks like the same as mine, but in method syntax and with a `ToList` on the end (and explicit generic type specifiers).
lc
Yep, I saw that. I like the method syntax to me it just looks cleaner.
David Basarab
+1  A: 

I have something similar but I was using it in more than one place so I created an extension method.

public static void ActOnCheckedRows(this GridView gridView, string checkBoxId, Action<IEnumerable<int>> action)
{
   var checkedRows = from GridViewRow msgRow in gridView.Rows
                     where ((CheckBox)msgRow.FindControl(checkBoxId)).Checked
                     select (int) gridView.DataKeys[msgRow.RowIndex].Value;

    action(checkedRows);
}

So now I can do something with all the checked rows. The compiler is pretty good at deducing the types but occasionally I need to explicitly declare checkedRows as type IEnumerable.

gvTasksToBill.ActOnCheckedRows("RowLevelCheckBox", checkedRows =>
{
    foreach (int id in checkedRows)
    {
       // do something with id
    }
});
David Clarke