Hi,
What is the best way (if there is any) to show pound signs instead of a number if a cell is not wide enough to display the whole formatted number? This is one of features in MS Excel. In order to do this, we need to be able to do at least the following tasks:
1) get the formatted number
2) get the font
3) get Graphics instance to call MeasureString on the formatted number with the font
4) get the width of the cell and it margins
Thanks,
Shaolin
Hi Shaolin,
Measuring the test yourself will be extremely difficult. But there might be an easier way. The grid and it's editors already keep track of whether or not the text fits inside the cell. They do this so the grid knows whether or not it's appropriate to show a tooltip.
So you could probably make use of that and then use a CreationFilter in order to change the Text of the cell to whatever you want without affecting the cell's value.
I decided to try to whip up a quick sample and it turned out to be surprisingly easy. My sample is attached here.
Hi Mike,
Thanks for your quick response and solution!
I tested your solution. Method IsTextFullyVisible is not always accurate.
Regards,
I played with the test app a little more and it is quite easy to reproduce what I reported. You press and hold down your mouse on the scroll box of the horizontal scroll bar and drag the scroll box to the far right and then slowly back to the left, all the strings and numbers will be displayed as pound signs as shown in the attached image.
Ah, okay, I see it now. I took a new approach and used a DrawFilter instead of a CreationFilter and it works correctly now.
If you are interested in why the first problem occurred, it's because the UIElements for the cell are verified when the column is initially visible. When you scroll, the position of the UIElements changes, but the contents don't, so the cell essentially doesn't get into the CreationFilter when scrolling back to the left and so it just keeps the # signs.
So the cell doesn't have to go through the CreationFilter, but it does have to re-paint, so a CreationFilter works okay.
There are two caveats to this approach, though.
First, you have to turn off ScrollWindow (via the UseScrollWindow property). This property optimizes the grid scrolling, but it prevents the cell from painting every time when scrolling. So there's a slight performance cost here.
Second, we have to wait for the TextUIElement to draw the text and then erase the text and draw the # signs. You might notice that in my sample, the Color cells don't work correct. This is because the TextUIElement in those cells has a transparent background. So if you are using colors in your grid, you would have to work around this by either hard-coding the color for the background drawing or else getting the resolved background color of the cell and using that.
This method does not work if an UltraGridColumn's CellDisplayStyle is set to CellDisplayStyle.FormattedText. There is no TextUIElement created for a CellUIElement, which would result in a better performance. I could see a tooltip showing when text is not fully visible inside the cell. Could you please give me some suggestions please?
Your help is greatly appreciated!
Best Regards,Shaolin
CellDisplayStyle sacrifices functionality for performance. So in this case, you would lose the ability to change the text on the element.
I think what happens in this case is that the CellUIElement draws the text, so you might be able to acheive what you want using a DrawFilter to draw the text yourself. But this would be much more difficult, since you would also have to measure the text yourself, instead of just letting the UIElement do it.
Thanks so much for your response!
I did exactly you said. Actually I never used a CreationFilter for this feature in the first place because I thought using a DrawFilter would be more efficient. The following is the code snippet:
case DrawPhase.BeforeDrawForeground: var cellElement = drawParams.Element as CellUIElement; if (cellElement != null) { string text = cellElement.Cell.Text; if (!string.IsNullOrEmpty(text) && text.Length > 1) { Size size = TextRenderer.MeasureText(text, drawParams.Font); if (size.Width > drawParams.ElementDrawingRectInsideBorders.Width) { text = new string('#', text.Length - 1); if(cellElement.Column.CellDisplayStyle == CellDisplayStyle.FormattedText) drawParams.DrawString(drawParams.ElementDrawingRectInsideBorders, text, false, false); else { var textElement = (TextUIElement)cellElement.GetDescendant(typeof(TextUIElement)); if (textElement != null) textElement.Text = text; } return true; } } } break;