【发布时间】:2018-01-24 00:59:06
【问题描述】:
在回答this question的过程中,我写了一些代码来保存和恢复DataGridView中单元格的选择状态。这个想法是保存状态,然后在用户单击网格后重新应用它,以模仿 DataGridView 通常不提供的“粘性选择”功能。我写的解决方案很好用。
作为我自己的练习,我决定重写一些代码以使用 LINQ 和流畅的语法。另外,我认为流畅的语法看起来很漂亮:) 你可以让 DataGridView 与 LINQ with the Cast<> method 一起工作。我的第一份工作是保存选择状态:
之前:
static private bool[][] GetSelectionState(DataGridView input)
{
int rowCount = input.Rows.Count;
int columnCount = input.Columns.Count;
var result = new bool[rowCount][];
for (var r = 0; r < rowCount; r++)
{
result[r] = new bool[columnCount];
for (var c = 0; c < columnCount; c++)
{
var cell = input.Rows[r].Cells[c];
result[r][c] = cell.Selected;
}
}
return result;
}
之后(使用 LINQ):
static private bool[][] GetSelectionState(DataGridView grid)
{
return grid
.Rows
.Cast<DataGridViewRow>()
.Select
(
r => r.Cells
.Cast<DataGridViewCell>()
.Select(c => c.Selected)
.ToArray()
)
.ToArray();
}
那部分也很好用。
但我无法将状态应用回 DataGridView。我知道这并不完全符合 LINQ 的精神(我认为它更适用于函数式/不可变类型的编程方法)。但我想我可以通过使用Zip 将单元格与存储的选择状态对齐并通过简单的赋值操作来应用它来欺骗它。这是我想出的。
之前:
static private void SetSelectionState(DataGridView input, bool[][] selectionState)
{
for (int r = 0; r <= selectionState.GetUpperBound(0); r++)
{
for (int c = 0; c <= selectionState[r].GetUpperBound(0); c++)
{
input.Rows[r].Cells[c].Selected = selectionState[r][c];
}
}
}
之后(使用 LINQ——这就是问题):
static private void SetSelectionState(DataGridView grid, IEnumerable<IEnumerable<bool>> selectionState)
{
grid.Rows
.Cast<DataGridViewRow>()
.Zip
(
selectionState,
(row, rowState) => row
.Cells
.Cast<DataGridViewCell>()
.Zip
(
rowState,
(cell, cellState) => cell.Selected = cellState
)
)
.ToList(); //Purge enumerator
}
^这会编译并运行,但完成后, Selected 每个单元格的属性都设置为 false。 em>
我也试过替换
.Zip
(
rowState,
(cell, cellState) => cell.Selected = cellState
)
...与...
.Zip
(
rowState,
(cell, cellState) =>
{
cell.Selected = cellState;
return cellState;
}
)
...还有...
.Zip
(
rowState,
(cell, cellState) =>
{
grid.Rows[cell.RowIndex].Cells[cell.ColumnIndex].Selected = cellState;
return cellState;
}
)
..但结果相同。
是否可以以这种方式使用 LINQ 从压缩的锯齿状数组中更新控件的属性?还是因为 LINQ 将所有内容都视为不可变,并复制所有内容,所以这是不可能的?是否有其他“LINQ-y”方法可以做到这一点?
【问题讨论】: