So I have a grid and I have merged "rows" together via certain columns containing identical values.
".MergedCellStyle = MergedCellStyle.Always.MergedCellStyle = MergedCellStyle.Always"
So what I want to do would seem to be a common task but I'm not seeing an answer. I want to create a "summary" for the "quantity" column of the rows that were merged together. I don't want to group the rows like normal because I like the look of the "merged" cells for this particular grid. AND I only want to display a total if more than one row is merged.
What am I missing? I'm pretty good with using draw filters, but the only way I could see to use a draw filter would be if there was something that fired AFTER the last cell was merged but before the next row was created.
I guess I could come up with a brute force way of doing this, but it just seems like it would be a common thing and I'm just missing something.
Thanks Mike,
I decided to go at it with a draw filter. That way I didn't have to worry about the update events. Here is what I my grid looks like:
In case some else wants to to do this and not have to think to much<G>:
Public Function GetPhasesToFilter(ByRef drawParams As Infragistics.Win.UIElementDrawParams) As Infragistics.Win.DrawPhase Implements Infragistics.Win.IUIElementDrawFilter.GetPhasesToFilter
Dim rVal As Infragistics.Win.DrawPhase = DrawPhase.None
If (TypeOf (drawParams.Element) Is MergedCellUIElement) Then
Dim mrgCell As Infragistics.Win.UltraWinGrid.MergedCellUIElement mrgCell = TryCast(drawParams.Element, MergedCellUIElement)
If mrgCell IsNot Nothing AndAlso mrgCell.Cell.Row.IsDataRow Then rVal = Infragistics.Win.DrawPhase.BeforeDrawElement End If
End If
Return rVal End Function
Dim LastRawID As Integer = -1
Public Function DrawElement(ByVal drawPhase As Infragistics.Win.DrawPhase, ByRef drawParams As Infragistics.Win.UIElementDrawParams) As Boolean Implements Infragistics.Win.IUIElementDrawFilter.DrawElement
Dim rVal As Boolean = True Dim elementRect As Rectangle Dim g As Graphics = drawParams.Graphics elementRect = drawParams.Element.Rect
'Load up some variables that releate to the cell. Dim theRow As UltraGridRow Dim theCol As Infragistics.Win.UltraWinGrid.UltraGridColumn Dim theCell As Infragistics.Win.UltraWinGrid.UltraGridCell Dim mrgCell As Infragistics.Win.UltraWinGrid.MergedCellUIElement
mrgCell = TryCast(drawParams.Element, MergedCellUIElement) theRow = mrgCell.Cell.Row theCol = mrgCell.Cell.Column theCell = mrgCell.Cell
'Grid has several merged columns, so I only want to do the spacing for the first column If theCol.Key = "RawItemDescrp2" Then Dim cRow As Integer = 0
'This is the KEY of the current merged row. Dim theRawID As Integer = theRow.Cells("RawID").Value Dim QtyTot As Integer = 0
'Loop thru the rows in the child band where we have merged cells For Each mRow As UltraGridRow In theRow.ParentRow.ChildBands(0).Rows
If mRow.Cells("RawID").Value = theRawID Then cRow += 1 QtyTot += mRow.Cells("ReqQty").Value 'Total up merged rows ElseIf cRow > 1 Then 'Once we have found another item then put some space between them. mRow.RowSpacingBefore = 30 cRow = 0 End If
Next
If cRow > 1 Then 'This handles merged rows that are at the end of the child band. theRow.ParentRow.ChildBands(0).Rows(theRow.ParentRow.ChildBands(0).Rows.Count - 1).RowSpacingAfter = 30 End If
If QtyTot > 0 Then 'This draws my sub total box Dim theRCell As CellUIElement = theRow.Cells("ReqQty").GetUIElement() Dim tRec As New Rectangle(theRCell.Rect.X + 1, elementRect.Y + elementRect.Height, theRCell.Rect.Width - 2, theRCell.Rect.Height) g.DrawString(QtyTot, mrgFont, Brushes.Black, tRec, mrgTotStrFmt) g.DrawRectangle(Pens.Black, tRec)
' I didn't like how the Merged Cell was rendering the text. I wanted it to word wrap. g.FillRectangle(New SolidBrush(Color.FromArgb(100, Color.Green)), elementRect) g.DrawString(theCell.Value, mrgFont, Brushes.Black, elementRect, mrgStrFmt)
rVal = True ' I handled the drawing of the element so I don't want the default drawing.
Hi Dan,
Well... if you want the sub-total to show up outside of the actual rows, then you have a few options.
One approach would be to add these sub-total rows into your data source and populate only the cells you want with the sub-total values.
I expect that you probably don't want to modify your data source, though. So another approach would be to do what I suggested previously - use the RowSpacingAfter or RowSpacingBefore property on the row to create a gap. Then you can use a CreationFilter to put some UIElement into that gap with the summary information you want. Since you want your sub-total on the bottom of the rows, it seems like using the RowSpacingAfter is the way to go.
In order to determine where to create the gaps, you will have to detect the last row in a set of merged cells. To do that, you could use the GetMergedCells method. So let's assume you have a grid cell in a column that supports cell merging and you want to know if that cell is the last merged row. You would do something like this:
private bool IsLastMergedRow(UltraGridCell cell) { UltraGridCell[] mergedCells = cell.GetMergedCells(); if (mergedCells != null) { int mergedCellCount = mergedCells.Length; if (mergedCellCount >= 2) { UltraGridRow lastMergedRow = mergedCells[mergedCellCount - 1].Row; if (lastMergedRow == cell.Row) { return true; } } } return false; }
You could loop through the grid rows any time something changes and update the spaces:
foreach (UltraGridRow row in this.ultraGrid1.Rows) { row.RowSpacingAfter = this.IsLastMergedRow(row.Cells["My Merged Column Key"]) ? 20 : 0; }
Then you have to call this loop from any place that might cause the merging to change. So the AfterCellUpdate event when it fires for the merged column, and maybe AfterSortChange, and possibly some other places.
Then you can use a CreationFilter to trap the AfterCreateChildElements of whatever UIElement contains the grid rows (RowCellIntersectionUIElement, I think). You would loop through the child elements looking for RowUIElement objects and get the Row from each one and check it's RowSpacingAfter. If it's 20 (or whatever arbitrary spacing you use) you can add some child UIElements into the parent element under the row (using the Rect of the RowUIElement as a reference point).
Thanks Mike!
Here is how I would describe what I'm trying to do. I have and order that I want to track multiple orders for a single Item. I "Merge" the columns that contain the "Item Name" and then each unmerged row has an Item Order Qty. So when the ItemID changes, I want to insert a subtotal row, for the rows that have the same ItemID.
Obviouly this would be easy if I "Grouped by" item id, but I already have a couple of group levels and it looks better with the merged. I don't "think" there is a way to "group" without having a group by row?
Yeah I see how to do this with a draw filter. But I will have to detect the ItemID change, and then move back a row and do the rowspacing thing. I was just "hoping" that there was something that would do this for me without having to go down that route.
Thanks,
Dan
Hi,
I'm not clear on exactly what you are trying to do.
Where do you want to put the subtotal?
I don't think that what you are trying to do here is very common at all, and the grid has no built-in subtotal functionality. So I don't think you are missing anything obvious here.
If you wanted to place the subtotal inside the Merged cell, then that could be done with a DrawFilter or a CreationFilter. I'd probably go with the latter, myself. But there would be an issue of where to put the sub-total if it did not fit. For example, if there are only 2 cells merged, then the cell's value could be aligned to the top of the merged cell and the sub-total on the bottom, and that would work, but you would probably want some way to distinguish the sub-total via color or something.
Another approach you could take would be to try using RowSpacingBefore and/or RowSpacingAfter properties to create a gap in between the rows where cells are merged.