I have a Hebrew calendar app where each day is a UserControl. I have 6 labels in that control for the English date, the Hebrew date, Jewish holidays and some other user-defined data. When scrolling, the labels' content changes as the date value for the UserControl goes up or down a week. The scrolling is noticeably slower than Microsoft Outlook Calendar, and profiling reveals that the part taking the longest is updating the label contents, which is not handled by my code.
Is there some way I can make this go faster? MS Outlook seems to have a comparable number of text fields, and the scrolling is smooth.
TextBlocks were not noticeably faster than Labels, but Glyphs gave my calendar whiplash.
Replacing this
<TextBlock Padding="5"
FontFamily="Narkisim"
FontWeight="Bold"
FontSize="20"
Text="{Binding HebrewDate}"/>
with this
<Glyphs Name="HebrewDate"
Margin="5"
StyleSimulations="BoldSimulation"
FontUri = "/Fonts/nrkis.ttf"
FontRenderingEmSize = "20"
UnicodeString = "5771 ןושח ה"
Fill = "Black"/>
made scrolling super fast.
Some notes:
Glyphs do not support binding, so I had to give each one a name and update them in the code behind, like so:
HebrewDate.UnicodeString = zman.HebrewDate;
Glyphs don't have Layout functionality so Hebrew text was coming out backwards. I had to preprocess the Hebrew strings with a reversing function. Even after reversing, the Hebrew vowel points came out misaligned, so I retained Labels for those strings which use vowels.
I can't be sure but it is possible that MS Outlook was coded in something faster than WPF, perhaps using DirectX to show the graphics rapidly.
Otherwise I might suggest toning down on the number of bindings updating at once, I would suggest using an additional thread to gradually update the labels as and when there are spare cycles instead of all at once, which might be causing your stuttering.
To go along with the previous answer, I recommend the background worker. Utilize the background worker for your most time consuming operation that gets executed during the scroll.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
Related
I have a textBox that grows vertically while typing. Unfortunately when I type a long text (for example a 3 line text) some PART of it gets blurry. What's more, when I prevent it from growing vertically and make it grow horizontally it works fine - the text is sharp then.
What I've tried:
UseLayoutRounding = true;
RenderOptions.TextRenderingMode = "ClearType";
Please forget about
TextOptions.TextFormattingMode = "Display"
It has to be "Ideal".
See the screenshots:
Disable SubPixel Rendering and Anti-Aliasing. Try
SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);
Since you mentioned:
I have a textBox that grows vertically while typing
I assume then that it's a CustomControl derived from TextBox and with a custom rendering to grow vertically instead of using the builtin text wrap ability.
Since I was unable to reproduce your issue with the stock TextBox and the parameters (with Ideal) you mentioned (I've checked from Framework 4.0 to 4.6 on VS 2013), maybe the blur comes from your custom code.
By the way, with not using the builtin wrap?
TextWrapping="Wrap"
Maybe you should include more code and details, like framework version, visual studio version, OS version and so on.
Likewise, specify your version of "Textbox that grows vertically". Something like this ?
Try increasing the font size of the textbox just a tiny amount (use 1/4s if in pixels). Alternatively, try changing the line height slightly in a similar fashion. I think the problem might be down to WPF's interpretation of the sub-pixels and may be rounding off at the wrong place.
We have a rather large WPF business application and I am working on a retool of an existing WPF FixedPage/FixedDocument report.
It's a somewhat busy ecosystem. We have a built-in forms generator, with lots of different controls you can put on (think like a mini built-in visual studio). All that works fine. You fill in the form on the screen, and then you can print out (to XPS) the identical copy to standard 8.5x11 paper.
In the code, we break out this report into vertical chunks. Say each chunk would be an inch or two tall on a printed piece of paper. This is how we handle pagination. If the next chunk is too tall for the page, we do a NewPage() and repeat. As I mentioned, this was working fine.
WPF has an enormous learning curve and I've been going back over old code and refactoring things and happily working with DataTemplates, strongly typed ViewModels, and generic ContentControls in order to reduce the size of our code. The on-screen forms generator still works, but the FixedDocument report has gotten weird.
Going back to those vertical slices, we print the user's forms to paper as individual Grid controls. Nothing fancy. Each grid (as I mentioned above) may be an inch or two high, containing any random mixture of checkboxes, radiobuttons, textblocks, and so on.
When the grids contained these stock (standard) MS WPF controls, I could do this all day long:
System.Windows.Controls.Grid g = .....
g.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
g.Arrange(new Rect(g.DesiredSize));
And get back proper sizes, i.e. 100 x 67.
Now, sometimes the grids have just one control - a header if you will (i.e. "This Month's Schedule). The only child control added to that grid is a ContentControl.
The ContentControl is simply bound to a ViewModel:
<ContentControl Content="{Binding}" />
There's then two DataTemplates in the resource dictionary that picks up this binding. Here, I'll show that:
<UserControl.Resources>
<w:MarginConverter x:Key="boilerMargin" />
<DataTemplate DataType="{x:Type render:BoilerViewModel}">
<render:RtfViewer
Width="{Binding Path=Width}"
TextRTF="{Binding Path=Rtf}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type render:Qst2NodeViewModel}">
<ContentControl Content="{Binding Path=BoilerVm}">
<ContentControl.Margin>
<MultiBinding Converter="{StaticResource boilerMargin}">
<Binding Path="NodeCaptionVm.Height" />
<Binding Path="NodeLeft" />
</MultiBinding>
</ContentControl.Margin>
</ContentControl>
</DataTemplate>
</UserControl.Resources>
The ContentControl will pick up that bottom-most datatemplate. That template will then in turn use the smaller one above.
The fancy converter just sets a margin. It may be fugly to read, but this all displays correctly on the screen within the parent usercontrol. It's all the right size and justification and all that.
On the printed report side (XPS), I have to create these controls in code and measure them to see if they'll fit on the current FixedPage. When I go to do this step: (on the grid containing this ContentControl)
g.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
g.Arrange(new Rect(g.DesiredSize));
I get back 0,0 size. Even though it should be like 730x27 for instance. Again, on the screen, hosted in a UserControl, this all works fine. Just trying to instantiate it and measure it purely in code fails. I've confirmed that the control is added to the grid, has its row and col set, has been added to the Children collection, etc...
If I prepend those two statements with an UpdateLayout call, like this, then it works:
g.UpdateLayout(); //this fixes it
g.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
g.Arrange(new Rect(g.DesiredSize));
I've been reading that UpdateLayout is expensive and to be avoided, and I'd rather not be calling this on each grid section before I add it to my FixedPage of the FixedDocument report. There could be dozens or even hundreds of iterations. And, again, if the Grid has regular WPF controls in it, without any ContentControls and fancy finding and looking up datatemplates, the measuring works fine without the UpdateLayout call.
Any advice? Thank you!
I just don't understand why it became necessary to start calling it once I started utilizing the Xaml engine. It almost feels like I'm being punished for using the advanced features.
Its complicated to explain that but let me try using plain words... In wpf everything works with dispatcher. Futhermore like you may already know dispatcher deals with tasks ordered by priority.
For example first a control is being initalized, then binding is being triggered, then values are updated, in the end all that is being measured.. etc etc
What you managed somehow is by setting all those contentcontrol inside contentcontrol stuff, you screwed up that order
Calling UpdateLayout basically forces dispatcher to finish its pending work in layout so you can work with clean layout afterwards
Screwing with dispatcher is quite common in wpf since some controls or values may be added later which ends in remeasuring things.
In your case you seem to be creating all at once in one method call without letting dispatcher take a breath. Therefore you need UpdateLayout method to normalize dispatchers queue.
I hope this helps you. You can also solve your issue by using Dispatcher.BeginInvoke.
UpdateLayout does not work in my case. I had to wait until dispatcher finishes processing of the layout tasks.
toPrint.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
Application.Current.Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle);
toPrint.Arrange(new Rect(new Point(0, 0), toPrint.DesiredSize));
I found another article about this approach.
I have tried both the regular TextBox and RichTextBox in an app where I don't want any word wrap. Yes, of course I turned off word wrap in Properties. This is something that occurs at extremely long lines, like around 3000 chars or so in the RichTextBox (regular TextBox much sooner, but I can get by without it if RichTextBox works). I recognize that it is cruel and unusual punishment to subject the poor RichTextBox to such line lengths, but unavoidable. Still, it seems like abnormal behavior.
The text is just long continuous strings of repetitive ascii (genetic data), so nothing unusual there. In fact it's usually just A,C,T,G with no punctuation or spaces.
Is this known behavior?
Assuming you are using WinForms, both RichTextBox and TextBox have built-in limits for lengths of lines.
An alternative is to use a scroll viewer and manually add Labels. I do not believe there will be any limit in this scenario, although I could be wrong.
If you check Notepad (notepad.exe) in Windows, it also has a limit before it starts wrapping text, so this is standard behavior for Windows apps.
the Multiline property should be false in order for the lines not to wrap.
You could try a RichTextBox and extend the right margin to the width of the text.
richTextBox1.RightMargin = TextRenderer.MeasureText(yourString, this.richTextBox1.Font).Width;
This way you maintain the ability to have other lines.
I need to create a control, that behaves like a textbox, but allows you to replace some (or all) of the characters with pictures that behave (select and remove with backspace/delete) as a normal characters.
I tried to create a RichTextBox inherited control, with "CanPaste - Paste" construction, but the images added this way didn't act like the characters, but as the images which can be resized. It's not a correct solution for me.
So, the question is: How can I override "symbol drawing" method? I mean, get actual (x,y) coordinates of drawing character, and draw picture instead of it (or in front of it). Is that possible?
Control should look similar to this picture. (lockers on picture are images, acting like symbols.)
UPD: Control must be working on systems from XP to 8, so using UTF-8 lock-style symbol won't be a solution for me. Control shown on the screenshot above works in an application that is running on a Windows XP — though I have no idea which way it was implemented.
What I would is use a PasswordBox with a FontFamily="Segoe UI Symbol" and the PasswordChar="& # xE14D;" (remove the spaces). This will render this:
The complete code: <PasswordBox Password="Example" Width="100" FontFamily="Segoe UI Symbol" PasswordChar="" />
I need to create a windows store application with e reader functionality. I have to provide a fluid reading experience. Currently, my knowledge of displaying text consists of dropping textblock or textbox on the UI. I do not know how to display large amount of text to create the E Reader experience i am looking for. Which control or combination of controls should i use?
Your text rendering options are
XAML controls
TextBlock
RichTextBlock
WebView + WebViewBrush
DirectWrite - what all the above ultimately use. You can use it with C# through SharpDX.
The controls might be a bit cumbersome to use at times if you need to do measurements etc. and might not give you as much power or performance as DirectWrite does, but will give you support for text selection, copying to clipboard etc. (make sure IsTextSelectionEnabled is set to true).
For measuring text dimensions for paged display in a TextBlock - create a TextBlock in code behind and call Measure() and Arrange(), then get ActualWidth/ActualHeight to get the measurement.
Read Charles Petzold's Principles of Pagination article.
Consider Rapid Serial Visual Presentation (RSVP) speed-reading method used in the ReadQuick app.