Here is my situation.
In the ultragrid implementation we have written, we have the HeaderClickAction set to SortMulti so that the user can sort by multiple columns. This works great. However, customers have reported to us the need to be able to visually see the sort hierarchy. In other words, if the user sorted first by column A, then B, then C, there is no way visually to see the sorting is done in that order based upon the sort indicators.
The only solution I see to this is to implement a creation filter that prevents the stock sort indicator from being created and implement my own indicator in it's place. But before I go down this road I thought it worth asking if anyone else has implemented a solution to this problem (or if maybe there is something native in the component that would accomplish what I'm trying to do).
It seems like anyone who has SortMulti turned on would have run into this situation before.
Thanks in advance
Chris Rowland
Thanks a ton Mike. Your answer was way above and beyond what I expected and it works like a champ. I would suggest what you have there should be stickied somewhere as I'm pretty sure it could be useful to others as well.
Again, many thanks.
This was actually a rather interesting DrawFilter, so I gave it a shot.
/// <summary> /// When used a DrawFilter for an UltraWinGrid, this class displayed numbers in the upper /// right corner of the colmn header to indicate the order of sorted columns. /// </summary> public class Sort_Order_Indicator_DrawFilter : IUIElementDrawFilter { #region IUIElementDrawFilter Members bool IUIElementDrawFilter.DrawElement(DrawPhase drawPhase, ref UIElementDrawParams drawParams) { // Make sure we are in the AfterDrawElement phase. This should always be the case // because that's the only phase we are returning from GetPhasesToFilter. if (drawPhase == DrawPhase.AfterDrawElement) { // Make sure we are processing a HeaderUIElement. This should always be the case // because that's the only element we are trapping for in GetPhasesToFilter. HeaderUIElement headerUIElement = drawParams.Element as HeaderUIElement; if (headerUIElement != null) { // Get the column. This should never fail, but check for null just in case. UltraGridColumn column = drawParams.Element.GetContext(typeof(UltraGridColumn)) as UltraGridColumn; if (column != null) { // Get the index of the column in the sorted columns collection. We are // trapping for sorted columns inside of GetPhasesToFilter, so we should never // get in here for an undosrted column. But check the index just in case. int sortIndex = GetSortIndex(column); if (sortIndex < 0) return false; // Add one, since the actual indices are 0-based. sortIndex++; // Create a font. In a real application, we would probably want to add a // Font property to this class so you could choose a font. But for // purposes of this example, we will just hard-code Arial 8. using (Font font = new Font("Arial", 8)) { // Create a brush. In a real application, we would probably // want to add a Color property to the class so you could choose // a color. But for purposes of this example, we will just use // black. using (SolidBrush solidBrush = new SolidBrush(Color.Black)) { // Align the text to the upper right corner. We will be using // the rect of the HeaderUIElement, so this will place the text // nicely above and to the right of the sort indicator. StringFormat stringFormat = new StringFormat(); stringFormat.Alignment = StringAlignment.Far; stringFormat.LineAlignment = StringAlignment.Near; DrawStringParameters drawStringParameters = new DrawStringParameters( drawParams.Graphics, sortIndex.ToString(), font, solidBrush, headerUIElement.Rect, stringFormat, GdiDrawStringFlags.GDIPlus, TextOrientationInfo.Horizontal); // Draw the string. DrawUtility.DrawString(ref drawStringParameters); } } } else Debug.Fail("Failed to get a column from the HeaderUIElement. Unexpected."); } else Debug.Fail("Got into DrawElement for an element that is not a HeaderUIElement. Unexpected."); } else Debug.Fail("Got into DrawElement for a phase other than AfterDrawElement. Unexpected."); return false; } DrawPhase IUIElementDrawFilter.GetPhasesToFilter(ref UIElementDrawParams drawParams) { // Trap for a HeaderUIElement if (drawParams.Element is HeaderUIElement) { // Get the column. UltraGridColumn column = drawParams.Element.GetContext(typeof(UltraGridColumn)) as UltraGridColumn; // Make sure there actually is a column. The HeaderUIElement might represent a // Group header, for instance, in which case we don't want to do anything. // Also, there's no reason to bother drawing anything unless the column is sorted. if (column != null && (column.SortIndicator == SortIndicator.Ascending || column.SortIndicator == SortIndicator.Descending)) { // If we get to this point, we know we are dealing with a column header for // a column that is sorted. So fire off the AfterDrawElement so we can draw // onto the header after it's done with it's normal drawing. return DrawPhase.AfterDrawElement; } } // Do nothing. return DrawPhase.None; } #endregion /// <summary> /// Returns the index of the specified column in the SortedColumns collection. /// </summary> /// <param name="column"></param> /// <returns></returns> private int GetSortIndex(UltraGridColumn column) { if (column.SortIndicator != SortIndicator.Ascending && column.SortIndicator != SortIndicator.Descending) { Debug.Fail("We should not be getting into GetSortIndex for the unsorted column."); return -1; } int index = column.Band.SortedColumns.IndexOf(column); if (index >= 0) return index; Debug.Fail("Failed to find the column in the SortedColumns collection. Unexpected."); return -1; } }
Hi Mike, I appreciate the response. At least I know there's not built in existing functionality that I'm missing.
In doing research for options available, I did initially try using a draw filter instead and actually tried what you proposed, putting a number inside the indicator. The problem I was seeing was that the draw appeared very random, and at times not painting when I thought it should.
Is there any chance you might possibly post a code snippet that I could compare against to see if what I was trying is correct? It would be greatly appreciated.
Chris
Hi Chris,
There's nothing built-in to the grid to show this, although it's a good idea, and I encourage you to Submit a feature request to Infragistics.
Rather than a CreationFilter, perhaps it would be simpler to use a DrawFilter an simply draw a number over the existing sort indicator to indicate the order. I've seen other applications that do it like that and this would be simpler than a CreationFilter, I think.