Hi,
Is there a way that the encompassing border for a group of rows sharing the same merge cell data be drawn differently?
To explain we have rows of data representing bookings. To make things easier for the user the cell data for the day of the week is set as a merge cell. This means that if there are three bookings for Monday then the user sees once nice Merged cell block for Monday and the three records. There would then be more data records for each day in the month etc..
This is very nice, however, users have asked is it possible to draw a thick line border around the whole 3 row blocks of data (The rows that share the same merge cell value) as it is difficult to distinguish between the day breaks...
Any thoughts would be appreciated. Ta
Cells in the grid do not draw all four side of their borders. If they did, you would end up with a double-thick border between each cell. So it's very hard to change the border of a single cell or a single merged cell.
What I would recommend is that you use a DrawFilter and draw an extra border inside the existng cell border.
If you are not familiar with DrawFilters, check out the Infragistics Knowledge Base which has lots of articles and sample DrawFilter code. Also, get the Infragistics UIElementViewer Utility. It's a huge help when dealing with UIElements.
What you want to do here is a pretty simple drawFilter, but if you get stuck, just post again here and I will try to help.
K just to make sure I dont get the wrong idea. What you are suggesting is to create a drawfilter that dynamically modifies itself. Thinking out loud it would need to retrieve the current row then determine if the row data has a merged value. Then it would need to determine the index of the row to find out if it is the top or bottom row of the merge block and then draw a fake border line appropriately?Remember it is the block of rows that I wish the border to go around. Is the above pseudo the right approach then?
Tbh you could ignore the _factory bit all it does is render the background of a cell similar to an appointment schedule view. But yes you could ignore that bit. As for :
For one thing, each ColScrollRegion has it's own set of UIElements, so you should not need to loop through them
I'm open to any ideas - I'm free to admit it is a bit dirty atm, just the documentation is a bit sketchy or more likely this is a bit more advanced than the usual.
Okay, then how about this approach:
public class MergedCellBorderDrawFilter : IUIElementDrawFilter { #region IUIElementDrawFilter Members bool IUIElementDrawFilter.DrawElement(DrawPhase drawPhase, ref UIElementDrawParams drawParams) { // This switch is really unneccessary, it's just a sanity check switch (drawPhase) { case DrawPhase.AfterDrawElement: // Another sanity check if (drawParams.Element is UltraGridUIElement) { UIElement dataAreaUIElement = drawParams.Element.GetDescendant(typeof(DataAreaUIElement)); foreach (UIElement element in dataAreaUIElement.ChildElements) { RowColRegionIntersectionUIElement rowColRegionIntersectionUIElement = element as RowColRegionIntersectionUIElement; if (rowColRegionIntersectionUIElement != null) this.ProcessRowColRegionIntersectionUIElement(rowColRegionIntersectionUIElement, drawParams); } } break; } return false; } private void ProcessRowColRegionIntersectionUIElement(RowColRegionIntersectionUIElement rowColRegionIntersectionUIElement, UIElementDrawParams drawParams) { Dictionary<MergedCellUIElement, Rectangle> borderRects = new Dictionary<MergedCellUIElement, Rectangle>(); foreach (UIElement element in rowColRegionIntersectionUIElement.ChildElements) { MergedCellUIElement mergedCellUIElement = element as MergedCellUIElement; if (mergedCellUIElement != null) { Rectangle rect; UltraGridCell cell = mergedCellUIElement.GetContext(typeof(UltraGridCell)) as UltraGridCell; if (cell != null && cell.Column.Key == "Int32 1") { rect = Rectangle.Empty; UltraGridCell[ mergedCells = cell.GetMergedCells(); foreach (UltraGridCell mergedCell in mergedCells) { UIElement rowElement = mergedCell.Row.GetUIElement(); if (rowElement != null) { if (rect.IsEmpty) rect = rowElement.Rect; else rect = Rectangle.Union(rect, rowElement.Rect); } } borderRects[mergedCellUIElement] = rect; } } } foreach (Rectangle rect in borderRects.Values) { using (Pen pen = new Pen(Color.Red, 3)) drawParams.Graphics.DrawRectangle(pen, rect); } } DrawPhase IUIElementDrawFilter.GetPhasesToFilter(ref UIElementDrawParams drawParams) { if (drawParams.Element is UltraGridUIElement) { return DrawPhase.AfterDrawElement; } return DrawPhase.None; } #endregion }
Very interesting will be able to try out in 2 hours - thank you very much for the input and continued response - its appreciated.
Thank you very much that was a big help I made some changes to account for rows where there are no merged cell records - ending up with :private void ProcessRowColRegionIntersectionUIElement(RowColRegionIntersectionUIElement rowColRegionIntersectionUIElement, UIElementDrawParams drawParams) { Dictionary<UIElement, Rectangle> borderRects = new Dictionary<UIElement, Rectangle>(); foreach (UIElement element in rowColRegionIntersectionUIElement.ChildElements) { MergedCellUIElement mergedCellUIElement = element as MergedCellUIElement; if (mergedCellUIElement != null) { Rectangle rect; UltraGridCell cell = mergedCellUIElement.GetContext(typeof(UltraGridCell)) as UltraGridCell; if (cell != null && cell.Column.Key == "ShiftDate") { rect = Rectangle.Empty; UltraGridCell[ mergedCells = cell.GetMergedCells(); foreach (UltraGridCell mergedCell in mergedCells) { UIElement rowElement = mergedCell.Row.GetUIElement(); if (rowElement != null) { if (rect.IsEmpty) rect = rowElement.Rect; else rect = Rectangle.Union(rect, rowElement.Rect); } } borderRects[mergedCellUIElement] = rect; } } else { RowUIElement rowUi = element as RowUIElement; if (rowUi != null) { // Account for rows that are not merged with any others UltraGridCell[ mergedCells = rowUi.Row.Cells["ShiftDate"].GetMergedCells(); if (mergedCells == null || mergedCells.Length < 1) { UIElement rowElement = rowUi.Row.GetUIElement(); if (rowElement != null) borderRects[rowUi] = rowElement.Rect; } } } } foreach (Rectangle rect in borderRects.Values) { using (Pen pen = new Pen(Color.CadetBlue , 1)) drawParams.Graphics.DrawRectangle(pen, rect); } }
I would like to say a big thanks for the support, cheers.
Nice job with this draw filter. I will have to file this away just in case I need this later on. Or perhaps Infragistics can write this up in a KB article??
K, given the last code stuff a bunch of testing, unfortunately, I ran into two problems :- The lines overwrite the vertical scrollbar if present
- The lines disappear if you scroll the grid data horizontally
So in a nutshell I'm back to my original attempt which so far touch wood works in all scenarios. I havent got any more time to invest working the weekend atm so I'm going to leave it at this. Thanks to everyone for the help, it was very informative.