Optimize rendering thousands of elements - c#

I'm facing a big problem with optimizing rendering a lot of custom controls. I'm developing a system that will be diplaying thousand custom controls and update several values of these controls every second or frequently. There will be also support for zooming and panning. But I found out that rendering(on canvas) takes a lot of time, zooming and panning is laggy.
Does anyone have an experience with this kind of wpf application?

In my experience this is almost always due to inadvertently disabling virtualization and container recycling, usually through styling/templating. My first step would be to examine the WPF Tree Visualizer at run-time and make sure you're only drawing the elements that are actually visible on-screen.

You can use BitmapCache to disable rerendering controls that have not changed.
In my experience this greatly improves zooming and panning performance.
Enable it for the more complex controls.
Example:
<Rectangle CacheMode="BitmapCache" />
<Rectangle>
<Rectangle.CacheMode>
<BitmapCache/>
</Rectangle.CacheMode>
</Rectangle>
Details here

Use 2 canvases that are the same size and at the same position (a top canvas overlaying a bottom canvas).
Bottom Canvas: displays all controls. This is a static image (cached) which might get refreshed every 30 seconds or so.
Top Canvas: displays every control that has changed in the last 30 seconds.
The 2 canvases are exactly aligned so every recently-changed control on the top canvas will exactly obscure its out-of-date twin on the bottom canvas.
This way you only have to draw the few controls that have changed rather than all thousand controls.

Related

Continous rolling of images from top to bottom in a image control in wpf c#

Good Morning. Image sliding from top to bottom is the known question only. But i tried with earlier answers, in that there is no continuity( when one image is sliding down another must enter from top ).
I tried with few slidings but not fruitful in continuity maintaining for a series of images in one image control only. As the work i have to prepate tick-tack kind game with 9 image controls individually sliding a series of images. When a image is selected sliding should stop and win conditions are horizontal or vertical or crosswise image equals.
Can someone help me with this. Thank you very much in advance.
Thanks,
Jagadeesh
I got the answer as for continuous rolling of images, two image controls in a container needs to be taken and with BeginTime difference they needs to be slided one by one and then with timer support this behaviour needs to be repeated. For not showing the images outside of image control borders, a scroll control needs to be attached to the container. If scroll control is not there while sliding they will appear above and below the borders of image control.

Dealing with very low animation frame-rates

Here's the scenario:
I've got a series of many views primarily containing listboxes. Listboxes, some with large amounts of data in them, some with very little.
Currently, I've got an attached behaviour that essentially just detects when new content has been loaded into the container for these views (a ContentPresenter) and triggers a simple XAML storyboard that offsets the container by 200px to the left, or to the right, and also lowers the opacity to 0% (at 0ms) then over 100ms it restores the opacity to 100% and reduces the offset back to 0px, creating a 'sliding into view' sort of effect.
Now, the issue:
The framerate of this animation varies horribly anywhere from a smooth transition to jittery, to outright just lagging at 1 frame until completion.
This is almost certainly due to the fact it's having to load the new view, render everything in it, then even further; lists with loads of data in them need even more render time, THEN whilst all that's happening it's trying to animate its location changing which seems to drastically affect the performance of the animation.
it shocks me that something as simple as moving some pixels across the screen is so graphically intensive for WPF to handle
Here's a crude representation of the animation itself:
My question:
Is there any sort of fundamental best-practice for dealing with intensive animations in WPF so as to improve their performance, or any kinds of small changes to things that when added up boost performance?
Or is WPF just terrible at animating and we just have to deal with it.
I think your problem is, that you try to do everything at the same time or same thread. Just try to do it async in splitted tasks. There are plenty of different approaches to that. Another approach would be to just handle the work with a semaphore, this should push your performance a bit up.
I've come up with a solution which, in my case, has always solved the jitter problem. It is certainly worth trying. The strategy is to take any element that will not change throughout the animation, insert it in a local reference framework such as a grid or canvas, make that grid or canvas store cached versions of its content, and then apply your animation to the grid or canvas, rather than the inside elements. It is as simple as this:
<Canvas ...Your canvas properties...>
<Canvas.CacheMode>
<BitmapCache />
</Canvas.CacheMode>
...Your UI elements...
</Canvas>
or, for a grid:
<Grid ...Your grid properties...>
<Grid.CacheMode>
<BitmapCache />
</Grid.CacheMode>
...Your UI elements...
</Grid>
You'll want to simply ensure that you do not update anything inside the canvas (or grid), as this will undo the cached version and you'll find yourself with a similar issue where WPF will regenerate its rendering on every frame.
By having cached versions of the content, what WPF will be moving across the screen is not a dynamically updated element, it is simply a bitmap of the last render of that element, and WPF will update that bitmap only if changes are applied to the element.
If that does not solve your issues, it means that performance is hindered by something occurring outside the generation of the local element. This means you'll want to look at your overall application, or reduce the entire frame rate of your application. However, in virtually all cases of jittering and jerky movements I found for my WPF animations, the BitmapCache solution seems to work all the time. Just be careful in not applying animations to objects inside the element being cached.

Define a dashboard panel with child resize logic

I am trying to write a XAML UI in WPF where the main window container (a panel) would host children.
The tricky part is I want the children to resize when the window resizes (e.g. when it's being maximized on a screen) and I want them to occupy the maximum of the available space without stretching.
But at the same time I would like them to be allowed to wrap like a wrap panel when possible.
I have designed a quick mockup for easier understanding.
Image mockup on Imgur (25.2KB)
The top one shows a panel hosting 3 elements which all share the same width and the same height. Two are on the first line, the third one takes advantage of the 2nd line to display.
If all were displayed on the first line, they would be of a smaller width.
The bottom one shows a panel hosting 8 elements which all share the same width and the same height (smaller than in the first mockup so they can fit in one screen). The first two lines have 3 elements each while the last line has only 2.
My initial idea was to use a Stackpanel but they strech your child elements and, as far as I know, they don't allow dynamic sizing of their children depending on the number of elements.
Then I had a look at the wrappanel which does the wrapping very nicely but requires you to set the children size in order to do its magic (I might have missed something but I couldn't find a way around it).
Do you have any idea how I could implement this behaviour while keeping my pannel flexible?
The application which is going to use it will have a different number of children to put in the panel depending on the user's settings.
Ah, I forgot to mention that there should obviously be no vertical scrolling, everything should fit on one screen like a dashboard. That's the point of this panel, make sure that everything fits but displays as big as possible, with no distortion.
If you have any question, just ask.
Thank you for your help.

Resolution for full screen WPF application

Following the guide here, I have created a full-screen WPF application. But I met a problem: the various size & resolution of screens. For example, I want to put several sprites on the screen as buttons; but they are located at different positions in each screen, and even different to what shown in the XAML designer.
I have searched all over without a clue got. How can I fix this problem? (to make the buttons appears the exact place (in the center), and better, help the xaml designer reflect exactly what will happens when the program is running). Any help will be appreciated.
UPDATE: I'm defining my page as a Canvas inside the Window element. Actually I like Canvas more, cause I can easily put my sprites anywhere, not like a grid.
In general, you should not use pixel values in WPF.
Instead, you should layout your content in <Grid>s with rows and columns, and it will automatically expand to fill the screen (based on the alignments and row / column definitions).
Avoid using the canvas. Also, do not rely too much on the designer to build your layout. Using Grids, Stackpanels and/or Dockpanels will give much better results (and scale when resizing your window). For example, if you use only the designer and drag-and-dropp all your elements, the designer often puts huge margins a bit randomly and this will not always scale properly if you resize your window.

How to center selected grid row/column at the center of the window?

I just wasted my entire evening on something which I thought would be very simple but it seems WPF and Google are letting me down completely.
I need a grid, 6x6 of which I fill every row and column with a custom control. I want to be able to navigate through this grid via the keyboard (I can get those events, no problem) but I cannot seem to find how I can always have the selected grid row/column in the center of my window.
I found some carousel alike implementations, but most of them only work in a single direction and I want two way navigation, yet none seem to support this nor can I extend them to do this.
I essentially want to create a PSP alike grid navigation.
One easy way is to do this:
Create a scrollable form.
Add a 6x6 grid of child controls.
In the GotFocus (or similar) event for all the controls, set the parent form scroll offset to an appropriate position to centre the child.
This is pretty straight-forward thing to implement, with a little bit of maths to work out how to centre the x,y position of a control by setting the scroll offsets (it can be tricky/confusing, but as long as you understand the coordinate systems used for scrolling, not too bad)
Or, another approach that avoids scrolling via the windows APIs and using custom controls:
Create a form
Override OnPaint to draw your grid of 6x6 "controls" as simple graphical shapes or bitmap images centred on the selected "control".
Handle keyboard (KeyDown/Up) and mouse handling (MouseDown/Up) events to make the 36 areas of the graphic respond to user inputs in the way you desire. You'll have to track the selected item and force the window to redraw its graphics to show the new state. Enable double buffering to stop it flickering.
The first approach gives you a lot of windows-based handling for free (tabbing between controls, remembering where the input focus is, and directing events to separate classes for each "control", for example). The second approach strips away all this "help" but gives you complete control over everything, which can often help avoid unintended behaviours (e.g. it won't move the input focus when the user presses Tab unless you specifically write the code to make it do that).

Categories