Multiple problems with WinForms DataGrid

P

Pete Davis

I have a Windows Forms datagrid with the datasource set to an ArrayList.

The ArrayList is initially empty.

I have DataGridColumn styles defined for 4 columns with widths, header
titles, and mapping names set.

The problems:

1: Now, I realize ArrayList doesn't implement IBindingList, so the
CurrencyManager won't get updated when I add items to the array.

I was under the impression I could simply do:

CurrencyManager cm = BindingContext[myDataGrid.DataSource] as
CurrencyManager;
cm.Refresh()

and that would fix it. Even though according to the watch window, I have 4
visible columns and 1 visible row after adding the row and calling
CurrencyManager.Refresh. Calling DataGrid.Refresh() does nothing for this
either.

The only solution I've found is to do something like:

grid.DataSource = null;
grid.DataSource = myArray;

But that seems stupid.

2: Column headers don't display unless there's data in the array. Is there
any way around this? I'd like them to display all the time because when
there's no data, it's just a big square empty control.

3: Using the code from George Shepard's Windows Forms FAQ, #5.11, I have the
grid set up so that clicking on a row selects the entire row on mouse up.

The problem is, when you press the mouse on a cell and don't let up, the
cell is selected. I tried duplicating the code in the MouseDown event, but
that doesn't work. Any ideas on how to fix that?

Thanks.

Pete
 
N

Nicholas Paldino [.NET/C# MVP]

Pete,

See inline.
1: Now, I realize ArrayList doesn't implement IBindingList, so the
CurrencyManager won't get updated when I add items to the array.

I was under the impression I could simply do:

CurrencyManager cm = BindingContext[myDataGrid.DataSource] as
CurrencyManager;
cm.Refresh()

and that would fix it. Even though according to the watch window, I have 4
visible columns and 1 visible row after adding the row and calling
CurrencyManager.Refresh. Calling DataGrid.Refresh() does nothing for this
either.

The only solution I've found is to do something like:

grid.DataSource = null;
grid.DataSource = myArray;

But that seems stupid.

You can create a wrapper around the array list which implements
IBindingList. You would have to expose the members of array list that are
relevant (like Add, Insert, Remove, and access to the indexer), but all in
all, it's not too hard.

I'm assuming you are not using .NET 2.0. If you were, you could use the
2: Column headers don't display unless there's data in the array. Is there
any way around this? I'd like them to display all the time because when
there's no data, it's just a big square empty control.

Yeah, that's a big gripe. Unfortunately, short of custom painting or a
third-party control, I don't know if there is anything you can do about it.

Hope this helps.
 
P

Pete Davis

Pete,
See inline.
1: Now, I realize ArrayList doesn't implement IBindingList, so the
CurrencyManager won't get updated when I add items to the array.

I was under the impression I could simply do:

CurrencyManager cm = BindingContext[myDataGrid.DataSource] as
CurrencyManager;
cm.Refresh()
[snip]
You can create a wrapper around the array list which implements
IBindingList. You would have to expose the members of array list that are
relevant (like Add, Insert, Remove, and access to the indexer), but all in
all, it's not too hard.

I'm assuming you are not using .NET 2.0. If you were, you could use
the DataGridView, and the BindingList<T> class, which implements the
IBindingList interface.

No, .NET 1.1. Actually, in fixing #2, I fixed this one as well, kind of by
accident. See below how...

Yeah, that's a big gripe. Unfortunately, short of custom painting or a
third-party control, I don't know if there is anything you can do about
it.
[snip]

In digging through the DataGrid code with Reflector, I determined that the
column headers weren't painting because the CurrencyManager can't get
PropertyDescriptors from the empty array. Why it needs them to draw the
information I've already provided in the ColumnHeaderStyles is beyond me,
but nevertheless, it apparently needs the property descriptors.

Attaching property descriptors to the ColumnHeaderStyles didn't work because
the grid just cleared them out.

What did work was to add a single dummy item to my array, bind it to the
grid, then remove the item from the array and call
CurrencyManager.Refresh().

By doing this, the grid was able to find PropertyDescriptors for the
columns, but deleting the row didn't delete the property descriptors, so the
column headers painted properly.

The lucky side-effect of this was that adding rows later and calling
CurrencyManager.Refresh() also worked, so #1 was fixed as well..

Any ideas on this? I'm thinking I'm going to have to derive a class from
DataGrid and handle the MouseDown event. I see more digging in Reflector in
my future.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top