I need to merge two column headers that are side-by-side into a single column header. How do I do that? I'd like the columns themselves to remain separate. I just want the header to look like a single header.
Hi,
There's no way to do this via simple property settings.
But there are a couple of ways you can achieve what you want. It's going to depend on what version of the controls you are using, though.
If you have a pretty recent version, then you could set the RowLayoutStyle on your grid to GroupLayout. Then you put the two columns into a group and hide the columns headers so that the group header takes the place of the column headers.
If you have an old version of the controls, then you may not have the option for GroupLayout, so you could use a RowLayout with an unbound column. You use the column.RowLayoutColumnInfo.LabelPosition to hide the column headers for the two real bound columns and hide the cells (LabelOnly) for the unbound column. The unbound column's header will act as the combined header for the two real columns.
A third option, which will work in any version of the grid but is a bit harder to implement it to use a CreationFilter to remove the UIElement for one of the column headers and extend the other into the empty space thus created.
This will be tricky, though, especially if you are not experienced with CreationFilters.
Mike, I'm pursuing the CreationFilter method, but I'm a bit confused. The code is below.
My problem is that BeforeCreateChildElements() gets called multiple times for the same headers without resetting the header rectangle to its original values and because of this, the code that calculates the rect, by adding the width of the adjacent column, continues to add that width over and over and over again, resulting in a column header that's ridiculously wide.
I can't seem to determine when it's getting called for the first time vs. the 5th time. How can I fix it so it only gets called once, or at least, only calculates the new header width once.
Thanks
public class ColHeaderSpannerCreationFilter : IUIElementCreationFilter { private string ColumnKeyMain { get; set; } private string ColumnKeyHidden { get; set; } private UltraGrid Grid { get; set; } public ColHeaderSpannerCreationFilter(UltraGrid grid, string colKeyMain, string colKeyHidden) { Grid = grid; ColumnKeyMain = colKeyMain; ColumnKeyHidden = colKeyHidden; } public void AfterCreateChildElements(UIElement parent) { } public bool BeforeCreateChildElements(UIElement parent) { if (parent is HeaderUIElement) { //Get a reference to the cell, and the cells ui element. HeaderUIElement headerUIElement = (HeaderUIElement)parent; UltraGridColumn headerCell = headerUIElement.Header.Column; // Left-hand column if (headerCell.Key == ColumnKeyMain) { UltraGridColumn rightCol = Grid.DisplayLayout.Bands[0].Columns[ColumnKeyHidden]; //This is a cell that should span two columns, so we stretch its rectangle. headerUIElement.Rect = new Rectangle(headerUIElement.Rect.X, headerUIElement.Rect.Y, headerUIElement.Rect.Width + rightCol.Width, headerUIElement.Rect.Height); return true; } // Right-hand column if (headerCell.Key == ColumnKeyHidden) { //Here we are hiding the cell by shrinking its height and width down to 0. headerUIElement.Rect = new Rectangle(headerUIElement.Rect.X, headerUIElement.Rect.Y, 0, 0); //Return true to let the grid know that we handled the event. return true; } } //Return false to let the grid know we did not handle the event. return false; } }
I tried to reproduce what you are describing using the sample that I posted here and I could not get it to happen. One difference, I think, it that in what you are describing, you are merging the headers for the first two columns and in my sample, it is columns 1 and 2 that are merged. So I changed the sample to merge the first two columns (0 and 1) and then moved another column and dropped it before column 0. But I am still not seeing any problem.
So whatever you are experiencing is probably related to some other property setting on your grid or else an error in the code.
Can you modify my sample to reproduce the issue and post it here so I can check it out?
Hi Mike,
I have modified the sample you have provided to re-produce the problem. I have just enabled column swapping feature of grid. Try to move any other column to the left of merged columns. You will get the behaviour about which Im talking.
Can you propose any solution to this problem?
I'm still not seeing anything wrong here. Here's what I did:
1) Run the sample.
2) Click on the column header for Column 3 to select the column.
3) Click and drag the column header for Column 3 and drop it before Column1.
I then see Column 0, Column 3, Column 1 (which is still the width of 2 columns), Column 4, etc.
Are you seeing something else?
I don't see how ColSwapping being on could possibly have any effect here, but I also tried swapping Column 3 with Column 1 and it still works just fine for me.
I do see a problem if you swap Column 3 with Column 2. Is that what you are doing? Clearly, this would not make sense, because this means you end up moving Column 2 so it is no longer next to Column 1. But that's not what you described here.
Using ColSwapping in this kind of scenario is probably a bad idea. But if you must have ColSwapping, the only thing I can think of is that you could handle the BeforeColPosChanged event and cancel any operation that results in Column 2 no longer being next to Column 1. This is probably not a bad idea to do anyway, just in case.
PFA video to reproduce the scenario.
Ahhh, okay, I see it now. I misunderstood what you wrote.
"When we move any other column(except the 2 columns whose headers we are merging) to left of 1st column(whose header is removed and 2nd header is extended), then extended header further increases its width to include other moved column header as well."
I thought you meant drag a column and drop it in front of the merged column. But you mean drag a column that is already in front of the merged column and drop it into a position after the merged column.
The problem here is that the grid determines where to place the dropped column using the UIElements, and the UIElement in this case is the UIElement for Column 1. In fact, it depends exactly where you place the mouse. If you drop when the mouse pointer is over Column 3, then it works fine, because the column is placed before Column 3. If the mouse is over the header for Column 1, then it breaks because you are dropping after Column 1 (in between Column 1 and Column 2).
When I posted this CreationFilter, I never really intended it to work with column moving. These columns appear stuck together, but they are not really joined in any way, so the grid cannot keep them together when moving columns around.
I think I was correct in my previous reply - if you want to be able to suppose column moving, then you will need to handle the BeforeColPosChanged and/or AfterColPosChanged event and fix-up any problems that may occur because the two joined columns got separated. This is not trivial undertaking because you will have to deal with all sorts of cases.
Dropping after Column 1 is one case.
Moving Column 1 itself is another.
And the user can drag more than one column at a time.
Can you provide any sample code to handle this scnerios?