I would like to perform an Except operation on set of items.
Code is like this:
IEnumerable<DataGridViewColumn> dgvColumns = dataGridView.Columns.OfType<DataGridViewColumn>();
IEnumerable<DataColumn> dsColumns = dataSet.Tables[0].Columns.OfType<DataColumn>();
Now, how to select Columns from dataSet.Tables[0] which are not in dgvColumns? I know that Columns from DataGridView are different type than Columns in DataSet. I want to pick up only a subset of common values. Like this:
var ColumnsInDGV = from c1 in dgvColumns
join c2 in dsColumns on c1.DataPropertyName equals c2.ColumnName
select new { c1.HeaderText, c1.DataPropertyName, c2.DataType, c1.Visible };
Above code selects me "columns" that are in both sets. So I tought I will create another set of "columns" that are in DataSet:
var ColumnsInDS = from c2 in dsColumns select new { HeaderText = c2.ColumnName, DataPropertyName = c2.ColumnName, c2.DataType, Visible = false };
and now that I will be able to perfrom Except like this:
var ColumnsOnlyInDS = ColumnsInDS.Except<ColumnsInDGV>;
But I am getting two errors:
So the solution would be to build a class and then use it instead of implictly - typed local variable. But I think that developing a class only for this reason is a not necessery overhead.
Is there any other solution for this problem?
You've almost got it. You just need to write:
// use () to pass a parameter
// type (should) be inferred
var ColumnsOnlyInDS = ColumnsInDS.Except(ColumnsInDGV);
instead of:
// do not use <> - that passes a type parameter;
// ColumnsInDGV is not a type
var ColumnsOnlyInDS = ColumnsInDS.Except<ColumnsInDGV>;
Update: So, the above actually doesn't work because Except
depends on comparing items in two sequences for equality; obviously, your anonymous type has not overriden object.Equals
and so each object that you create of this type is treated as a distinct value. Try this* instead:
var dgvColumns = dataGridView.Columns.Cast<DataGridViewColumn>();
var dsColumns = dataSet.Tables[0].Columns;
// This will give you an IEnumerable<DataColumn>
var dsDgvColumns = dgvColumns
.Where(c => dsColumns.Contains(c.DataPropertyName))
.Select(c => dsColumns[c.DataPropertyName]);
// Then you can do this
var columnsOnlyInDs = dsColumns.Cast<DataColumn>().Except(dsDgvColumn);
*Note: Where
in the above expression for dsDgvColumns
makes more sense than SkipWhile
because it will apply the specified filter over all results. SkipWhile
would only apply the filter as long as it was true and would then stop applying it. In other words it would work if your DataGridViewColumn
not bound to your DataSet
were at the beginning of the DataGridView
; but not if it were in the middle or at the end.