考虑下面的当前算法迭代GridView
的行,以查找是否选中/选中了包含的Checkbox
。
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()));
}
}
这可以按预期工作:你留下了一个完全填充的List<int>
。
问题:您如何使用LINQ重新编写或改进此算法,以便在GridView
中搜索已选中/选中Checkbox
的所有行?
答案 0 :(得分:20)
我很确定你不会从中获得任何性能提升,但它可能会让稍微更容易阅读:
var checkedIDs = from GridViewRow msgRow in messagesGrid.Rows
where ((CheckBox)msgRow.FindControl("chkUpdateStatus")).Checked
select Int32.Parse(messagesGrid.DataKeys[msgRow.RowIndex].Value.ToString());
同样,不确定它会有所作为。另外,为什么要转换为字符串然后转换为int?是否有Convert.ToInt32
无法为您做的事情?
答案 1 :(得分:9)
我不确定Rows是否是IEnumerable他们可能不是,但我会假设他们是
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>();
我只是在记事本中执行此操作,可能存在编译错误。但这就是你如何用Linq做同样的事情。
答案 2 :(得分:4)
我有类似的东西,但我在不止一个地方使用它,所以我创建了一个扩展方法。
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);
}
所以现在我可以对所有已检查的行执行某些操作。编译器非常擅长推断类型,但偶尔我需要显式地将checkedRows声明为IEnumerable类型。
gvTasksToBill.ActOnCheckedRows("RowLevelCheckBox", checkedRows =>
{
foreach (int id in checkedRows)
{
// do something with id
}
});