Hi,
I am looking for a way to turn off the display of the Sort Indicator on a sorted column while retaining the ability for the user to sort the column.
I have searched the forum and found a similar question - the suggested fix was to use a CreationFilter on the grid to cancel the creation of the SortIndicatorUIElement.
This does stop the indicator being displayed - however my problem is that the space is still made for the indicator anyway. How do I prevent this?
This results in wrapping of the header text unless I resize the column to fit the updated column header.
I have very strict (and unique!) requirements to save as much space as possible to resizing the column is not an option. I need to hide the indicator AND stop the grid reserving space for it also.
I have tried numerous workarounds involving resetting the columns SortIndicator property to None. This does the trick when sorting Ascending however when sorting Descending it reverts the sort to Ascending :-(
Any suggestions are most welcome.
Thanks!
One way you might be able to do this is to take advantage of the fact that when you set the SortIndicator on the column to None, the grid does not un-sort the column. So if you set the SortIndicator to Ascending, then force the grid to paint, you can then set the SortIndicator back to none to remove the indicator, while the column remains sorted.
Something like this:
private void ultraGrid1_InitializeLayout(object sender, Infragistics.Win.UltraWinGrid.InitializeLayoutEventArgs e) { e.Layout.Override.HeaderClickAction = HeaderClickAction.Select; e.Layout.Override.SelectTypeCol = SelectType.None; } private void ultraGrid1_MouseUp(object sender, MouseEventArgs e) { // Get the grid. UltraGrid grid = (UltraGrid)sender; // Get the last UIElement entered by the mouse. UIElement element = grid.DisplayLayout.UIElement.LastElementEntered; // Try to get a column header. Infragistics.Win.UltraWinGrid.ColumnHeader columnHeader = element.GetContext(typeof(Infragistics.Win.UltraWinGrid.ColumnHeader)) as Infragistics.Win.UltraWinGrid.ColumnHeader; if (columnHeader != null) { // Get the last sort direction of the column from the tag property on the // column header. SortIndicator? sortIndicator = columnHeader.Tag as SortIndicator?; // Toggle to sorting. switch (sortIndicator) { case SortIndicator.Descending: case null: sortIndicator = SortIndicator.Ascending; break; case SortIndicator.Ascending: sortIndicator = SortIndicator.Descending; break; } // Store the new sort direction in the tag. This is so we can clear the // SortIndicator property on the column, but still remember which direction // the column was last sorted. columnHeader.Tag = sortIndicator; // Get the column. UltraGridColumn column = columnHeader.Column; // Force the grid to sort. column.SortIndicator = (SortIndicator)sortIndicator; column.Band.SortedColumns.RefreshSort(true); column.Band.Layout.Grid.Refresh(); // Un-sort. column.SortIndicator = SortIndicator.None; } }
There are a couple of caveats, though.
1) The grid sorts lazily. This means that in order to sort the grid, you will have to force it to paint while the SortIndicator is set. This is easy enough to do, but it means there will be a little flicked in the column header while the sort indicator appears and then disappears. To get around this, you can probably use the same CreationFilter you referred to here.
2) Since the SortIndicator on the column is getting cleared, you will need to remember which columns are sorted and in what direction. In my sample code here, I use the Tag property on the column header. But my implementation here is incomplete. I did not, forexample, clear the tag of all of the other columns when you sort a column. I also didn't attempt to deal with multi-column sorting.
Thanks a lot Mike - that sounds like a great idea. I'll give it a try!
Hi Mike
I finally got time to try out your suggestion and unfotunately the "flicker" you mention when refreshing the grid to force it to sort is proving a problem. It is acting differently for different columns (perhaps based on the header text width or the column contents width) but I have tried a lot of variations in the Creation Filter (see code below) to try and move the sort indicator out of the way and remove it altogether but nothing seems to work - the problem remains that the grid seems to be trying to find somewhere to put the indicator.
Any ideas would be very welcome. I am having trouble attaching an image from my machine showing the effect of the flicker but basically it shows one column's header text bouncing right, one bouncing slightly left and one column header increasing in height. In call cases I think it's trying to make space wherever it can for the sort indicator even though it has been removed. Below is the code for my creation filter. Thanks in advance!
public class RemoveSortIndicatorCreationFilter : IUIElementCreationFilter
{
private int sortIndicatorHeight = 0;
if ((parent.Parent is HeaderUIElement) && (parent is TextUIElement)) // HeaderUIElement) // SortIndicatorUIElement)
// only play with the text element size if this column is sorted
// Expand the text element to take account of the missing indicator
Rectangle origRect = descripElem.RectInsideBorders;
origRect.Left,
origRect.Top,
origRect.Height
);
}
this.sortIndicatorHeight = origRect.Height;
0,
0
// remove teh sort indicator element
parent.Parent.ChildElements.Remove(parent);
parent.Dispose();
// Return false so PositionChildElements will get called to do the default child element creation.
// nothing to do in this method
#endregion
Hm. I'm not sure why this isn't working. Your CreationFilter must be doing something differently when there is and is not a sort indicator. This CreationFilter also appears more complicated that I think it needs to be.
I tried this and it seems to work:
public class RemoveSortIndicatorCreationFilter : IUIElementCreationFilter { #region IUIElementCreationFilter Members public void AfterCreateChildElements(UIElement parent) { if (parent is HeaderUIElement) { UIElement sortIndicatorUIElement = parent.GetDescendant(typeof(SortIndicatorUIElement)); if (sortIndicatorUIElement != null) { Rectangle rect = sortIndicatorUIElement.Rect; UIElement textUIElement = parent.GetDescendant(typeof(TextUIElement)) as TextUIElement; textUIElement.Rect = parent.RectInsideBorders; parent.ChildElements.Remove(sortIndicatorUIElement); } } } public bool BeforeCreateChildElements(UIElement parent) { return false; } #endregion }
This assumes there's nothing but text in the column header (i.e. no images).
Thank you! Your better (and simpler) creation filter alone solves the problem. I do not even need the MouseUp code to artifically do the sorting. Setting HeaderClickAction on the grid to SortSingle and using your creation filter to hide the indicator does the job perfectly. I think my creation filter was trying to this the wrong way and failing to remove the space occupied by the sort indicator.
Thanks again for all the help!