I have a Windows Forms application with a DataSet
. I've simply used the Data | Add New DataSource to add the Products table of the Northwind database to my DataSources and created a DataGridView
showing the contents of开发者_Python百科 the Products table. I just dragged the Products table from the Data Sources window to the form, so all the columns are created automatically.
Now, I want the rows containing a product where the Discontinued column is true to be painted in a different color. I've created a CellPainting
event handler for it, but I'm having trouble locating the value for the Discontinued column.
Because the DataGridView
is created automatically, the Columns in it have names like dataGridViewTextBoxColumn1
, which has a DataPropertyName
of "ProductID".
My question is: how can I find the value for Discontinued based on the DataPropertyName
? Or am I required to use the name of the column itself? (In which case I better give it a meaningful name)
My code is:
private void productsDataGridView_CellPainting(object sender,
DataGridViewCellPaintingEventArgs e)
{
if (e.RowIndex >= 0)
{
var row = productsDataGridView.Rows[e.RowIndex];
if ((bool) (row.Cells[ nameOrIndexOfColumn ].Value))
{
e.CellStyle.ForeColor = Color.DarkGray;
}
}
}
How can I access the Value of the Column with DataPropertyName
"Discontinued"?
Solution
Based on Neil Barnwell's answer, this seems to be a way.
private void productsDataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.RowIndex >= 0)
{
var productView = (DataRowView) productsDataGridView.Rows[e.RowIndex].DataBoundItem;
var product = productView.Row as NorthwindDataSet.ProductsRow;
if (product != null && product.Discontinued)
{
e.CellStyle.ForeColor = Color.DarkGray;
}
}
}
The big advantage of this is that the Discontinued value doesn't have to be an actual column on the DataGridView.
Don't get the value from the column in the grid, get the value from the actual datarow that populates the gridrow. This way you can avoid all the magic strings etc.
There's a little bit of casting to be done because the [Type]DataRow
is hidden inside a DataView
that's attached to the grid, but it is a more elegant approach (and far less brittle in case of future changes) if you integrate it nicely into your code than relying on magic strings.
Here's an old blog post of mine that describes in detail how to do it:
http://koder.wordpress.com/2010/04/09/getting-data-from-a-winforms-datagridview/
UPDATE
You've mentioned that you're using Northwind and that you've "simply dragged the Products table to the form", so I'm guessing this isn't a mission-critical piece of software, but for the benefit of other people reading, I just wanted to suggest that this wouldn't be a typical approach any more in a real application.
Typically these days we'd consider having a Domain Model, perhaps using an ORM to obtain our Domain Objects from the data store (of course datasets aren't a real ORM), then possibly using things like MVVM to build data structures optimised for binding to UI elements from those Domain Objects.
Using this approach, because you have the actual data to hand in your ViewModel, you can calculate such rules as colours etc from the real data, and the UI simply displays the results of applying those business rules.
Why don't you try giving a name to that particular column yourself and then you know how to access it. Visual studio shouldn't have any problem with this even if its auto generated. Because it was generated to help you do all the binding and column creating stuff in the background. But it is still available for editing, autogenerated doesn't mean it generated at run-time . Its just helping you do the usual stuff, but you can still edit it.
row.Cells[ nameOrIndexOfColumn ]
You can try something on these lines
if (dataGridView1.Columns[e.ColumnIndex].DataPropertyName == "Discontinued")
{
if (dataGridView1[reqdColumnIndex, e.RowIndex].FormattedValue as bool)
{
e.CellStyle.ForeColor = Color.Gray;
}
}
reqdColumnIndex is the column which has your bool value
精彩评论