I currently have a 952 large collection of items. I am displaying about 500+ of them as polygons, and this is causing some noticeable, but manageable lag in my application. What is the most lightweight control / element that I can use to display these items at one time?
DrawingVisuals provide a more lightweight approach for rendering objects than Paths:
http://msdn.microsoft.com/en-us/library/ms742254.aspx
The downside of this approach is that they do not provide events such as mouse enter / leave, you must perform hit testing manually. However, this might be OK for your needs.
There is an even more lightweight approach where you add items to the visual layer directly, you can see an example on this page:
http://msdn.microsoft.com/en-us/library/ms748373.aspx
My advice would be to try DrawingVisuals first.
Related
I need to display a very large amount of data in a list view, up to 5 million or more rows. I am trying to find a solution where I can show all of the 5 million of items without having all of the 5 million items in my applications memory.
So basically the idea is that only a small amount of the items are shown, like 1k or 2k and when scrolling new data is retrieved from a database on demand. So that the application never has more then a couple of thousand item in its application memory. However the user should not realize that this is done, the listview should behave as if it had 5 million rows. Which means if he drags the scrollbar way down it should display the last of the 5 million rows and not the last of the couple of thousand rows that are currently in memory.
Does anyone of you have concept how such a feature can be achieved? I am grateful for any input you can provide.
Thanks,
m00ni
Data virtualization in wpf is much discussed - here is a good starting place.
I have implemented an approach that is somewhat different from anything I've found online. It isn't perfect but it suits my needs quite well.
I have a generic ItemsProvider interface that can page through data and exposes some other basic functions and info about the backing data. I also created a VirtualizationManager class that inherits from DependencyObject and has dependency properties ScrollableHeight and VerticalOffset. These are bound to the matching properties on a ScrollViewer (found in the templates of your finer ItemsControls). When either of these properties change they fire a callback that calculates how close the scroll viewer is to the end of the (currently loaded) list - for this my VirtualizationManager needs a handle to the ItemsProvider - and if that is less than some minimum amount the ItemsProvider is instructed to load the next page. The whole contraption can be installed on an ItemsControl via a set of attached properties.
My implementation is rather idiosyncratic, but the idea is fairly simple.
If you're dealing with very large lists you'll want a solution that not only loads incrementally but also unloads old items. There is at least one such solution at the link above.
I'm working on an app, that displayes huge (10000+ elements) graphs in a wpf canvas.
I'd like a feature like in Visual Studio, when you can split the view of an editor (so I can view two distant part of the same graph at the same time).
I have some constraints:
data binding (creating the bindings) of graph elements makes the loading of big graphs very slow, so I'm not using MVVM, the "VM" knows about the view and updates it directly when needed
the children of the canvas are frameworkelements, since I use the Tag property
because of the number of graph elements, I don't want to keep two different view for each element for the two part of the split view
So it should be like displaying multiple parts of the same canvas in different places. You can't set two parents for the FrameworkElements in WPF, so the easiest way is out of question :(
What are my options? Should I reconsider my constraints or there is some workaround for this?
Let me know if you need any more details (it's a big application, so I can't give you every information).
Edit: duplicating with visual brush is not an option since I need proper input event notifications, so both view must be editable.
Options:
Bind the same data to two controls.
Use a visual brush and duplicate input on the real control.
Create a custom graphing control that can output two parts of the graph at once.
If binding to two controls is too slow, then I think you need to rethink your application. The very fact that you have so much data displayed at once that you need a dual view to see separate parts is disturbing. That should raise a red flag. The red flag would notify you that, "What I need, and what I have is different." And you should go back to the drawing board and find out what you really need.
Otherwise, it might be best to create a custom control. The graph is rendering in its entirety even though you only need small portions displayed. If you had your own custom control you could speed up the entire app by rendering only visible portions at a time, and splitting within the control.
At a high level my application is applying about 5 different DataTemplates to a set of ListBoxItems based on their type. These items are laid out on a canvas at specific x, y points. I implemented virtualization on my ListBox and it did not seem to improve the time it takes to complete the rendering thread's processes. It still takes about 8-12 seconds for the UI to be completely loaded and usable by the user. I thought virtualization would help fix this problem but after looking around it looks like it only helps process scrolling large amounts of data. Am I correct in this assumption and does anyone else have any other tips for improving the rendering thread. This is the only problem I am having and then my project is complete. Thanks StackOverflow!
Virtualisation means that only the items you have visible are created, then dynamically destroyed/new items created as you scroll. The alternative is all UI controls are created for all items at once.
It sounds like you have bigger problems with the rest of the app. Do you perform all loading operations on a background thread? Is the UI control tree very complex indeed? Are you displaying 100s or 1,000s of items?
We also had a lot of trouble with performance in WPF. Best way is of course to profile your application. We use ANTS Performance profiler for that, but any .NET profiler will do. We got a huge performance hit, because of the lookup of our XAML Resources. Thats the advice i can give you:
Try to minimize all resources in XAML. But not only that, also try to minimize the amount of XAML files you have. One thing you can try is to defere the loading of complex parts of your DataTemplate. Similiar to what happens when you load a JPEG in a browser, first you will see a pixelated image which will be finer after it finished loading the JPEG. To accomplish that, use a simpler DataTemplate at first and then if this is visible only load the complex template on demand or after a while.
But without more information of your specific problem, we can only guess. This is an old question of mine about a similiar subject, maybe this will help aswell.
Yes, ListBox virtualization is for scrolling. When you have a large number of items in a ListBox, enabling virtualization will make only the visible items (+ a few extra items for scrolling) render, and scrolling the ListBox replaces the data in the rendered items instead of rendering new items.
If you were to post some code, perhaps we could assist you with some performance tweaks
In case a screen of a WPF application contains lots of primitive controls, its rendering becomes sluggish. What are the recommended ways to improve the responsiveness of a WPF application in such a case, apart from adding fewer controls and using more powerful videocard?
Is there a way to somehow use offscreen buffering or something like that?
Our team was faced with problems of rendering performance. In our case we have about 400 transport units and we should render chart of every unit with a lot of details (text labels, special marks, different geometries etc.).
In first our implementations we splitted each chart into primitives and composed whole unit's chart via Binding. It was very sad expirience. UI reaction was extremely slow.
So we decided to create one UI element per each unit, and render chart with DrawingContext. Although this was much better in performance aspect, we spent about one month improving rendering.
Some advices:
Cache everything. Brushes, Colors, Geometries, Formatted Texts, Glyphs. (For example we have two classes: RenderTools and TextCache. Rendering process of each unit addresses to shared instance of both classes. So if two charts have the same text, its preparation is executed just once.)
Freeze Freezable, if you are planning to use it for a long time. Especially geometries. Complex unfreezed geometries execute HitTest extremely slow.
Choose the fastest ways of rendering of each primitive. For example, there is about 6 ways of text rendering, but the fastest is DrawingContext.DrawGlyphs.
Use profiler to discover hot spots. For example, in our project we had geometries cache and rendered appropriate of them on demand. It seemed to be, that no improvements are possible. But one day we thought what if we will render geometries one time and cache ready visuals? In our case such approach happened acceptable. Our unit's chart has just several states. When data of chart is changed, we rebuild DrawingVisual for each state and put them into cache.
Of course, this way needs some investments, it's dull and boring work, but result is awesome.
By the way: when we turned on WPF caching option (you could find link in answers), our app hung up.
I've had the same perf issue with a heavily customized datagrid since one year, and My conclusion is:
there is basically nothing you can do
on your side (without affecting your
app, i.e.: having fewer controls or
using only default styles)
The link mentioned by Jens is great but useless in your case.
The "Optimizing WPF Application Performance" link provided by NVM is almost equally useless in my experience: it just appeals to common sense and I am confident you won't learn anything extraordinary either reading. Except one thing maybe: I must say this link taught me to put as much as I can in my app's resources. Because WPF does not reinstanciate anything you put in resource, it simply reuses the same resource over and over. So put as much as you can in there (styles, brushes, templates, fonts...)
all in all, there is simply no way to make things go faster in WPF just by checking an option or turning off an other. You can just pray MS rework their rendering layer in the near future to optimize it and in the meantime, try to reduce your need for effects, customized controls and so on...
Have a look at the new (.NET 4.0) caching option. (See here.)
I have met a similar problem and want to share my thoughts and founds. The original problem is caused by a virtualized list box that displays about 25 complex controls (a grid with a text block and a few buttons inside displaying some paths )
To research the issue I used the VisualStudio Application Timeline that allows to how much time it takes to render each control and PerfView to find out what actually WPF is doing to render each control.
By default it took about 12ms to render each item. It is rather long if you need to update the list dynamically.
It is difficult to use PerfView to analyse what heppens inside since WPF renders item in the parent-child hierarchy, but I got the common understanding about internall processes.
WPF does following to render each item in the list:
Parse template using XAML reader. As far as I can see the XAML parsing is the biggest issue.
Apply styles
Apply bindings
It does not take a lot of time to apply styles and bindings.
I did following to improve performance:
Each button has its own template and it takes a lot of time to render it. I replaced Buttons with Borders. It takes about 4-5ms to render each item after that.
Move all element settings to styles. About 3ms.
Create a custom item control with a single grid in the template. I create all child elements in code and apply styles using TryFindResources method. About 2ms in the result.
After all these changes, performance looks fine but still most time is spent on loding the ListControl.Item template and the custom control template.
4. The last step: replace a ListControl with Canvas and Scrollbar controls. Now all items are created at runtime and position is calculated manually using the MeasureOverride and ArrangeOverride methods. Now it takes <1ms to render each item from which 0.5ms is spent on TextBlock rendering.
I still use styles and bindings since they do not affect performance a lot when data is changed. You can imagine that this is not a WPF solution. But I fave a few similar lists in the application and it is possible not to use templates at all.
My app has many controls on its surface, and more are added dynamically at runtime.
Although i am using tabs to limit the number of controls shown, and double-buffering too, it still flickers and stutters when it has to redraw (resize, maximize, etc).
What are your tips and tricks to improve WinForms app performance?
I know of two things you can do but they don't always apply to all situations.
You're going to get better performance if you're using absolute positioning for each control (myNewlyCreatedButton.Location.X/Y) as opposed to using a flow layout panel or a table layout panel. WinForms has to do a lot less math trying to figure out where controls should be placed.
If there is a single operation in which you're adding/removing/modifying a lot of controls, call "SuspendLayout()" on the container of the affected controls (whether it is a panel or the whole form), and when you're done with your work call "ResumeLayout()" on the same panel. If you don't, the form will have to do a layout pass each and every time you add/remove/modify a control, which cost a lot more time. see: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.suspendlayout(VS.80).aspx
Although, I'm not sure how these approaches could apply when resizing a window.
Although more general than some of the other tips, here is mine:
When using a large number of "items", try to avoid creating a control for each one of them, rather reuse the controls. For example if you have 10 000 items, each corresponding to a button, it is very easy to (programatically) create a 10 000 buttons and wire up their event handlers, such that when you enter in the event handler, you know exactly which element you must work on. However it is much more efficient if you create, lets say, 500 buttons (because you know that only 500 buttons will be visible on the screen at any one time) and introduce a "mapping layer" between the buttons and the items, which dynamically reassigns the buttons to different items every time the user does something which would result in changing the set of buttons which should be visible (like moving a scrollbar for example).
Although, I'm not sure how these approaches could apply when resizing a window.
Handle the ResizeBegin and ResizeEnd events to call SuspendLayout() and ResumeLayout(). These events are only on the System.Windows.Form class (although I wish they were also on Control).
Are you making good use of SuspendLayout() and ResumeLayout()?
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.suspendlayout(VS.80).aspx