views:

218

answers:

1

I am trying to bind a collection (that inherits from BindingList) to a DataGridView. The grid headers show up fine and the I get the number of rows that I expect. However, the cells are empty. Has anyone else had this problem? If so, how did you resolve it? I've talked to someone else who had the same problem but they can't remember how they resolved it. I've tried to create a simple version that shows the problem but haven't had any luck. So I'm sorry, I haven't included any code.

EDIT #1:

I don't think this code will help but just in case. I have simplified things in order to prevent from having to outline the 47 layers of our code. But like I said, I can't recreate the problem with a very simple example like this. I'm not really wanting code analysis--just words of wisdom from those who have run into this problem. Surely I'm not the only one.

public interface ISearchResultCollection : IList<ISearchResult>
{
...
}

public class SearchResultCollection : BindingList<ISearchResult>, ISearchResultCollection
{
...
}

public interface ISearchResult
{
  ILineNum LineNumber {get; set;}
  string Text {get; set;}
}

public class SearchResult
{
...
}

ISearchResultCollection results = objectToSearch.Find("searchstring");
dataGridView1.DataSource = results;

EDIT #2:

I think I've got a lead. All of the public properties on my interface that represents an item (ISearchResult) are interface types as well. I added a string property and its data is magically showing up. So, in the above example, the Text column's data would show up. But, the LineNumber column's data would not since it is of an interface type (ILineNum). I figured ToString() would be called to populate the grid on these. Any ideas now?

A: 

When you databind an object to some control, the databinding interfaces will automatically call "ToString()" on your object so you get a decent string representation in whatever control you are binding to. In the case of a DataGridView you will see the ToString'd representation of the underlying object in the appropriate cell. However, when you databind to an interface, no such call to ToString() is made. This means that your DataGridView will display an empty cell but this is quite misleading as the bound object is actually there as it should be - it just doesn't have any value to display in the cell.

To fix this you need to deal with the formatting of a display value yourself. In a DataGridView, this can be achieved by handling the CellFormatting event. This event is fired whenever any cell needs to format its value so you must be careful not to put too much heavy logic in this handler. In your case, all you need to do is call "ToString()" on the underlying object. So you can handle the CellFormatting event then use something like this in your handler:

private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    if (e.Value != null && dataGridView1.Columns[e.ColumnIndex] == theRelevantColumn)
    {
        e.Value = e.Value.ToString();
    }
}

In the above snippet we are checking for a specific column before performing the logic but this is optional, your own scenario may be different. The main point to note is that we get the original object passed in on the event args and all we need to do is set the formatted value back in the event args. In this case, the formatted value is generated by calling "ToString()" on the underlying object. In your DataGridView, you will now see this formatted value in the appropriate cell.

Hope that helps.

Anon