How to access a cell in a DataRowView based on the columns DataPropertyName?

13,245

Solution 1

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.

Solution 2

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 ]
Share:
13,245
comecme
Author by

comecme

Updated on June 04, 2022

Comments

  • comecme
    comecme almost 2 years

    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 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.

  • comecme
    comecme about 13 years
    The problem is exactly how to find the right column. So I don't know the reqdColumnIndex.
  • comecme
    comecme about 13 years
    Well, that's quite a bit of casting taking place. It's too bad you first have to cast the DataGridViewRow to a DataRowView, and then cast its Row property to the desired DataRow type. But anyway, your post sure helped me. I'll add my C# implementation to my Answer and mark your answer as the answer.
  • comecme
    comecme about 13 years
    That's what I meant by "Or am I required to use the name of the column itself? (In which case I better give it a meaningful name)".
  • Shekhar_Pro
    Shekhar_Pro about 13 years
    Unless you want to dive in a coding adventure you should Simply name the column .. thats why the name property is there. ;-)
  • Neil Barnwell
    Neil Barnwell about 13 years
    Glad it helped. The need to cast is a shame, but as far as I can make out it's necessary. Of course you could optimise it by caching etc, but essentially this is the approach to take.