First of all: I am going to provide an answer to this question myself, as soon as I'm done.
But you may help me on my way to it, I will appreciate all of your advices.
I have a DataGridView with different rows that belong together. My problem is to find a suitable way for displaying and working with these connected rows.
My first idea was keeping each row individual, but that has some disadvantages:
how to clearly show that rows belong together?
I could add another column whose cells show the same number for connected rows, but that's not easily visible and requires another column.
My solution here would have been that all connected rows have the same background colour, and the colour changes e.g. between white and light grey for each set of connected rows.how to work with connected rows? As soon as I select one row of a set, I would have to analyse this row by extracting information (saved in a cell's tag or in a hidden cell) which rows belong together and select them as well. Even bigger work for moving rows up/down in a DataGridView: I would have to analyse the neighbouring row sets as well to see how far I have to move.
Therefore I decided to create a DataGridViewMultiRow
.
I will post the full code of that class here as an answer when finished.
It will inherit from DataGridViewRow
("DGVR") and store a list of single DGVR or of other multi-rows and display them as one by drawing the cells of the row by own code. However, I still need to find out which events to use for that purpose. MSDN suggests to use DataGridView.RowPrePaint
, but I rather want to use an event that is bound to the DGVR itself. Maybe I will analyse the source code of DataGridViewRow.Paint() and write my own method...
The single rows will be made invisible when being added to a multi-row (they could be switched to visible again by abusing the concept, but there's a lot in .net itself that is not protected against abuse; maybe I don't even switch to invisible, so it's in the user's responsibility).
Recursion in the multi-rows will simply be avoided by forcing each DGVR to be part of the same DGV as the multi-row, and because each row can be added to only one DGV and only once, I don't have to check for recursion any more.
Now I am struggling how to implement the internal list of rows. I was thinking about using the .net DataGridViewRowCollection
, but I found that it's operation is tightly bound to the DataGridView
itself: a DGV can have only one DGVRColl, but each DGVRColl refers to a DGV. So there would be half-connected DGVRColl in each of my DGVMultiRow.
I was going to ask whether this will this cause issues, but I already found that I must provide a DGV when instantiating the DGVRColl, which I don't have at that moment when the DGVMultiRow ctor is called. Furthermore, when using a DGVRColl and providing a public get property to it, I can only hook to the 'CollectionChanged' event and have no control over the individual operations like Add()
and Remove()
. So I will use a simple private list.
Continuation #1
I got the main work done, it looks pretty good already:
I still need to get details fixed, like placing the text correctly when the scrollbar is moved and other small things.
I decided not to override the DataGridViewRow.Paint()
because that one has too many internal connections. So I first played with using the CellPainting
event of the DGV, which was a good start. But I needed to have infos of all cells of the row at the same time, so I went forward to overriding the DataGridView.RowPrePaint()
as suggested by MSDN, see link above. This works really well.
To be continued.
After various drawbacks, I have finally created a solution.
It is written in C++/CLI, so most of you will have to adapt it for usage in C#.
This solution contains some user functions that are not part of the solution, but whose purpose should be easy to guess by their names.
Here's a preview: