WPF: slow template instantiation - c#

I have a WPF application, and it's slow.
It is NOT the rendering. Firstly, the rendering is quite simple, and secondly, I looked at it with WPF Performance Toolkit - nothing.
It is NOT in my own code. Firstly, the unit tests work fast, and secondly, if I replace all DataTemplates with blank ones, everything works fast.
So far, it looks like the slow part is template instantiation. That is, when you start the application, and open some complicated screen, it takes a lot of time. And by "a lot" I mean "a lot". Sometimes can be as much as 3-5 seconds - for example, when there's a datagrid with 100 rows. But when you go to another tab, and then go back to that same screen, it opens fast (as long as its viewmodel stays put).
This is very annoying not just because it's slow, but because I can't do anything about it. If I had some control over the slowness, I could, maybe, display some "opening, please wait" message or something...
Besides, when I look at some other WPF applications (most notably, ILSpy), they seem to work reasonably fast, despite the large amounts of data. This makes me believe that I'm probably doing something wrong. But I have no idea where to start.
Any ideas? Any classic mistakes? Any tips?

My exerience comes from working on the WPF mind mapping application NovaMind
A couple of months ago we completely rewrote our intermediate layer to solve the performance issues we had experienced. In a nutshell, creating our user controls seemed to be way to slow. Unfortunately I couldn't find a great way to profile the performance as neither the WPF Performance Suite nor commercial applications such as ANTS Profiler give you any detailed information on this part of the WPF process. (I asked this question back then)
We resorted to manually test our application by trial and error and removed parts of our user controls to see what exactly is the culprit.
In the end we solved the performance issues by completely rewriting our controls. We also cut down on the complexity of our visual tree dramatically. Before the rewrite, one of our most used user controls, when inspected with Snoop, consisted out of 61 different things, now there are only 3. Wherever possible we only added things to the visual tree on demand. (As you know in XAML even when you set things to Collapsed, they need to be created first).
Finally we were forced to write our own rich text rendering control as the built in RichtextBox is ridiculously slow and the visual tree of the RichtextBox is quite complex.
I don't know if this will apply to your situation but I would recommend that you investigate your user controls and see if they are complex. Maybe you have things that you could trim.
Low hanging fruits would be parts that are only rarely visible or can be created in a lazy manner. You could create these parts from code behind when necessary rather than having them in XAML. This should help you a lot.
Otherwise virtualization is your friend, if possible. In our case we couldn't do that unfortunately.

This sounds similar to a problem i was having. I posted the fix here: WPF UI Automation issue . Just posting for the benefit of searchers, as it took ages to resolve.
Following comment on link only answer, here is the crux of that post:
I did the following:
Downloaded Hotfix - - http://archive.msdn.microsoft.com/KB978520 (may not be required)
Downloaded Hotfix - - http://archive.msdn.microsoft.com/KB2484841 (definitely required even if you have Windows 7 / .NET 4)
Improved the code further (the validation was causing an excess of objects) - Why does WPF Style to show validation errors in ToolTip work for a TextBox but fails for a ComboBox?
It may be that only Number 3 was required, but it worked. Just posting here so people dont lose the days I lost in memory profilers etc.

User Control in your data template, is not completely bad idea but if you crave for performance then you should consider switching to lighter control. For example, having a UserControl just hosting a TextBox is very bad idea, as UserControl is made up of ContentControl, ContentControl hosts ContentPresenter and ContentPresenter will host TextBox so if you notice your Visual Tree, it has three new layer of UI Elements. Reducing Visual Tree will certainly improve the performance.
Most likely, I would suggest creating Custom Controls that may be a completely a new control having few dependency properties that can relate to data you want to present and you can have its own custom template in generic.xaml. Second, you can just simply derive a control from existing controls and redefine its default template in generic.xaml.
This approach will certainly work better as you will be reducing your Visual Tree, thus reducing Visual State Manager's job.
Changing theme or template will be slower then changing the element that hosts content. And let the element have the default template in its own generic resource dictionary.

Try moving all the resources up as
far as they'll go, preferably into
app.xaml
Check if you could use StaticResource
instead of dynamic ones, static ones
are alot faster
If possible, try using depedency
properties in your VMs, especially if
you have alot of them at once or if
they have alot of properties. That will keep wpf from having to do a bunch of reflection.

You mention you are using a DataGrid with, say, 100 rows. A likely culprit of your perf problems is that whatever datagrid you are using isn't doing virtualization, and so your visual tree is gigantic.
Normally, long startup time in WPF screens points to a large visual tree.
I'm not sure if you're using a datatemplate per row, or some 3rd party grid that binds columns, or what - but lets say you have 8 columns with controls. Depending on your grid/validation/etc, this could be a visual tree of 20-60 items per row. If you have a combobox, then each item in the dropdown may be created per row as well.
To fix this just takes watching the details, and taking measures as you go:
Use a virtualizing control as much as possible. This means using a virtualizingstackpanel inside list controls, and making sure your 3rd party controls do as well (many stock WPF controls do now by default)
Do not overuse UserControls, composite controls, etc. Adding depth adds time, and putting in extra visual tree depth in a datatemplate or other repeated area adds up fast.
If all else fails, show a simple screen and add controls through code to improve perceived performance

Related

How to make a Windows Form to change it height adaptively as controls get added/removed or hidden/shown?

What I need can probably be described as "reverse-anchor", "reverse-dock" or something like that (I have chosen to mention this just because "reverse-anchor" happened to be the first thing to come into my mind as a keyword candidate when searching for questions and answers that might already have been submitted discussing this subject, perhaps this will help people thinking a similar way to find this one in future). WinForms controls implement the Anchor property to set up adaptive resizing on containing control/form size change but I need the opposite - the form to resize adaptively to the controls.
A thing adding a minor bit of complexity to the task is that the controls meant to be added/removed/shown/hidden/enabled/disabled (and resized perhaps - this functionality is not really needed directly so far but I suspect it can turn to be required for compatibility with non-default Windows visual styles and themes that have potential to affect controls sizes unpredictably and can change at any moment of the app running) are not going to be the last ones on the form - a row of buttons will always be in between of the last control of the volatile group and the window lower border.
The actual task is to design a form that will display a collection of objects with a row of controls (a label, a text box and 0-2 buttons) corresponding each of them and it is strongly preferable to use just the very basic "common controls" avoiding grids, lists and stuff like that in this case (wrapping them in an additional container controls like panels is perfectly acceptable though, abstracting them in a separate "user control" can be considered too if this can really make the solution easier, more reliable or otherwise better, using hand-written code manipulating controls and form sizes is perfectly acceptable too (I can hardly expect a "set a magic property and it's done" kind of solution to exist for this task) but I haven't found a reliable algorithm so far (when to change what properties and what formulae to calculate new values with)).
The maximum capacity can be safely limited to something near 10 (or 20, perhaps, but not more - more would be just absolutely unreasonable to display on one form (provided scrolling is not an option)) so both ways are acceptable: to add/remove the controls in runtime or to put them on the form in the designer and just manipulate Visible and/or Enabled properties in the code. By the way I have found a problem with Visible - it gets switched off and back on by the framework internals before the form is rendered and other controls Anchor properties come in the game but I don't think it's a good idea to rely on this to happen always and the same way so just adjusting the form Size property on a control Visible property change does not feel really convenient).
What might be some good ideas relevant to implementing this behaviour?
PS: As far as I know this is a natural feature of WPF but I am to use WinForms to make the app runnable on Macs and, perhaps, other non-Windows platforms with help of Mono.
I'll tell you about some clues may help you:
1- correct to build your own Procedure for manipulating all the matter.
2- i advice to use a Wizard methodology (Next / Back buttons) so if the plate form is small like tablet or smart phone, so the mentioned procedure will decide how many Controls combinations (Label, text box, option button...) will be in each frame of that wizard and keep the remaining for Next button.
3- By the way if you will hide some controls use the original event fires to run the mentioned Procedure. (like a basic button to start the form so don't depend on visible / resize events).
4- Resize the size of each form of the wizard in the last part of the mentioned procedure.
If still a problem exists tell me and i hope i can help :-)

Is there a lot of overhead in a User Control?

I am working on a WinForms project which feels sluggish. It is composed of a literally hundreds of User Controls. If there is a piece of a UI functionality (even if not used anywhere else in the app), it's encapsulated in a User Control. I've gone through the project a number of times with the ANTS profiler and most of the heavy code appears to be in various control constructors.
Before I start ripping out User Controls, do they represent significant overhead to a WinForms application versus just laying out the form without User Controls (e.g. just intrinsic controls)?
A user control is a container for other controls. Having hundreds of them probably means you have multiple hundreds of windows in your project. A window is a very expensive operating system object. They start to noticeably drag down painting perf when you have more than 50 or so.
The comparison to Outlook is apt. That's a good sized chunk of a program. It has less than 50 windows. Easy to see with Spy++.
The difference is OnPaint. Microsoft wrote a lot of code, they didn't drop a lot of controls on a form.
I've been in User Control hell and it's not fun. A few things I've noticed:
If you have too many user controls and move your form around or scroll, you can wind up with a lot of white flickering as the drawing operations of deeply nested window handles fight for rendering time. This is particularly noticeable when you first open up the form.
Beware of nested user controls in the designer. If you open a user control in the designer, the constructor won't be called (it actually generates the designer surface by parsing the compiler-generated code.) However, user controls used by that user control will have their constructors called. This is usually not a problem, but it's worth knowing about if you see odd things happening.
If you have a large solution with lots of user controls, VS 2008 will take a long time to enumerate all of your projects to find all possible controls the first time you open the designer pane. This is a relatively minor annoyance, but it can consume time.
That said, User Controls are definitely handy and worth using in moderation. The main thing I try to avoid is overly deep nesting. I've found that WPF is much better in this respect. It has full control over the rendering pipeline, so you don't get the repainting issues associated with deep composition of controls.

Silverlight: Auto scrolling page when tabbing to different textbox

I am using silverlight 2.0 with C# for my application.
Few of the pages are quite long and contain quite a few of textboxes. The question I have is:
I use 'tab' to move between the textboxes on the page. When I tab into a TB that is not shown on the page - how can I make it so that the pages autoscroll to display which field I am on the page?
Right now I have to manually scroll the page. I have tried couple of things and would like to know if there is an easier more efficient way to accomplish this.
Thanks in advance!
Here is a behavior that looks good for the "scroll into view" issue. I haven't tried it myself though, so I cannot vouch for the quality (and I don't know if it works in Silverlight 2):
Silverlight BringIntoView() extension method (with OnGotFocus behavior)
And I very much recommend migrating to Silverlight 3 (and later this year, 4) if you are planning on doing more work on the application. It is hard to say how difficult it will be for you, especially since you are new to Silverlight. That depends on the nature of your application. I can only say that when we migrated from 2 to 3 it was not that difficult, and we have a big application with a lot of strange hacks. I was expecting a world of pain, but it was done in a couple of days. Oh, and you can get the Telerik components for version 3 as well.
I would suggest that you try compiling the app in Silverlight 3 with the upgraded Telerik components and see how many build errors you get. Then you will probably have a pretty clear indication of whether it's worth it or not.

Control to view a file with a large amount of text

Is there a TextBox-like WinForms control that can show a large amount of text (hundreds of megabytes) in read-only mode? Of course it should work without loading the whole file into memory at once.
I'm trying to implement this myself, using a standard TextBox, processing scroll and keyboard events and reading the amount of text necessary to fill the visible "window". But it's still quite buggy, and I'm feeling that I'm reinventing the wheel.
Loading "hundreds of megabytes" of text into a control sounds like a very, very bad idea memory/performance wise; it will likely crash your program. Anyway, how are you going to read all those millions of lines? Do you really need the whole text in there all the time? Mabye it would be better if you had a buffer and loaded small amounts of text into a RichTextBox and when you reach the end (or even near the end), simply load up the next 100 (or any other amount) of lines. Or, if you are searching for something, search for your keywords and put the relevant text in the RichTextBox. It really depends on what you are planning to do.
I think you got best chances by using Scintilla or its wrapper Scintilla.Net. I think it doesn't it job that perfect, but it makes it much better than TextBox or RichtTextBox.
I've no knowledge of such a control (RichTextBox is slow when you put a single wikipedia page into it, so I'm quite sure he loads everything into memory).
My experience with the winforms is that you often need to customize defaults controls to obtain the behavior you want, even when it seems trivial (nullable DateTime anyone ?). On the other hand, they do offer a good base to add one or two simple behaviors quickly without having to do all by yourself.
I've been using winforms controls for several months and often ended up implementing specific (some trivial, others complex) behaviors in my own controls.
There is no such control from what I know. Long time ago I have written similar control but it is for Delphi, but the principles are the same (read limited block of data and render it). So if you decided to implement it by yourself, then move away from TextBox control, it is not well suitable for such needs. I believe you should create new Control descendant with all custom painting. It is not very easy, but it is the only correct way.
Display the text in parts.....10.000 characters in each text box....i recently discovered thet if you make the textbox bigger the program will run faster when editing the text or scrolling...

What is a fast way to render a log view in WPF?

I'm writing an application that needs a log-like view, (similar to how an IM client displays messages in the conversation), with potentially many updates per second. Speed is an issue here; the application locking up due to a large number of incoming events is a possible problem. I need selection and basic text formatting, so manual rendering could get quite complex, I'd like to avoid it if possible. I'd also like to bottom-anchor the scroll bar, that is, if it's at the bottom, stay at the bottom when the new item is added. What would be a good way to implement this?
You can implement it very easily in WPF.
Create an ObservableCollection of Log entities and bind to a ListBox.
Give a DataTemplate for the ListBox.ItemTemplate.
*When running in real time you need either UI side or Data side virtualization
Check out my PaginatedObservableCollection so that the DataVirtualization will automatically function.
I think you should have a look at ListView/ListBox controls, they support UI virtualization and provide functionality you're looking for. Also you can improve performance by data virtualization/lazy loading - i.e. don't hold invisible items in memory and load required data on demand

Categories

Resources