In my XAML UI, I have 4 canvas panels.
At a time only one is visible and others are collapsed.
I am using transform to have horizontal sliding effect while displaying a canvas.
I have two options to do this:
option1:
When I want to goto a Canvas, I move all other 3 canvases out of screen because i dont know which one is currently active. Advantage of this is I have only 4 animations, one for each canvas.
option2:
I define new animation for going to a particular canvas from another particular canvas. In this case I do not need to move all three canvases but only one. But then I need to create12 animations, 3 for each canvas.
I think option 1 is memory efficient since only 4 animation instances are there but there is CPU performance overhead.
Option 2 is CPU efficient but causes memory overhead due to 12 animation instances.
Which option should i prefer?
Thanks,
Tushar
Just out of interest, have you considered using the VisualStateManager? By defining an 'OnScreen' and 'OffScreen' VisualState via a style, and applying that to each of the Canvases, you would only have to code it once, let the VisualStateManager call the whichever animation is appropriate by using VisualStateManager.GoToState() which means you don't need 12 animation instances, and you don't need to call 4 animations every state change. Best of both worlds?
If you need more information, I can provide some example code shortly.
it looks like you've thought through the implications of each approach rather well. Unfortunately, only you can answer the question that you've posed. If memory is of concern to your application, then you should go with option 1. But if your application is sensitive to being CPU-bound, then you should go with option 2.
I know that's largely a non-answer ... but as it always is with performance, you should do some profiling and testing of both approaches. You may find that the relative benefits or drawbacks of both approaches is negligible, in which case you should go with whatever option is more maintainable and easier for you to code (probably option 1) :-)
Related
I have a ListView with different complex ListViewItem containers consisting of images, shadow effects, blur effects.. etc. Rendering these containers in large amounts heavily reduces performance, especially since i'm using a blur overlay frame on top of the ListView. Which is why in this case i'm setting CacheMode to BitmapCache (improves performance by up to 15x the fps).
<Border.CacheMode>
<BitmapCache />
</Border.CacheMode>
The problem is that i use a WrapPanel and a ValueConverter to dynamically resize and fit these containers into the WrapPanel so that they completely fill the space in either horizontal or tile views. Apparently, that doesn't work well with caching and it produces severe lags/stalls (frame drops to 0).
Currently my 3 options are:
Disable caching (and live with almost 15fps)
Disable resizing (looks unacceptable)
Disable caching and resizing only when resizing window (still performs bad but it's the best option i have)
My questions:
Why do i get these huge drops in performance while resizing with caching vs without caching?
Am i misusing caching or doing it wrong?
Is there a better way of fixing this mess without compromises?
Ok. After a lot of reading and experimenting, i figured two things:
First, Caching should not be used on elements that resize frequently, especially if they're too many (couldn't find out why). So, i basically cached fixed size child elements instead.
And that reminded me of Virtualization which was exactly what i was missing but didn't know was supported in WPF Lists.
With some more optimizations, now, i can resize the window buttery smooth.
I'm working on a form that shows many our company's products in a FlowLayout, but on some categories that hold many products, performance in scrolling is noticeably affected. I switched to a List so I could leverage the performance benefits of using a renderer, but now I'm not happy with the layout since there's a lot of wasted space, especially if the device is in landscape mode.
My next thought was to use a Table, which I believe also uses renderers to optimize the display of its data; but to mimic a FlowLayout, I'd need to get the preferred width of some placeholder component, then divide the container's width by that to get the number of columns, and then fill the model with that number of columns in mind. I'd also need to change all that if the device changes orientation.
Before I go down that rabbit hole, I'm wondering if I'm making things unnecessarily complicated for myself and if there's already something that I can use to achieve that goal. So to summarize, what would be the most efficient way to display data (that would be shown as buttons) sequentially from left to right, and top to bottom?
I wouldn't use FlowLayout for anything serious although I doubt its the reason for your performance issues, those probably relate to something else. There is a performance how do I video which is a bit old but mostly still relevant: http://www.codenameone.com/how-do-i---improve-application-performance-or-track-down-performance-issues.html
In design terms flow layout is hugely problematic since the elements are not aligned properly thus producing a UI that doesn't look good when spanning multiple rows. I suggest using a grid layout which has a mode called auto fit. By using setAutoFit(true) on a grid of even 1x1 all the elements will take up all available space uniformly based on screen size and adapt with orientation changes.
In my WPF app I have a control representing a pack of 20 cards (each about 150x80 px) that fan out in an arc, so they're all slightly overlapping in the centre of the arc. When the control is added there's an animation to fan them out.
After that, the fan/control can be moved around, and when the user hovers over a card it expands and then goes back to normal size when they move off it.
This all works fine, but has a noticeable effect on performance- everything is very jerky, presumably because when other things move all the overlapping stuff and transforms in the control are being constantly recalculated/redrawn.
Any suggestions for how I can improve performance while still keeping individual cards in the fan responsive?
To find the source of the slowdown you need to profile.
Try to find out whether or not WPF is switching back to software rendering or not.
After that try to run on a different computer with other (better) hardware/graphics card.
If it doesn't get any better there might be errors in your app.
I have a WPF application with many tabs..
in one tab.. i make a verycomplex vector drawing consisting of thousands of drawing visuals.. (this represents a machine and all elements need to be interactable..)
It takes 3/4 seconds for drawing this for the first time..After the first draw it should be done..
The problem is if i switch to another tab and comeback, it takes atlease 2,3 seconds to show the tabpage with drawing again.. Since there is no redraw, why should it take so much time..?
If the component is not going to change, you could call Freeze() on it to mark it as done. Without trying it out I don't know if that would help, but you could give it a shot.
Not all objects are Freezable. Check out the MSDN documentation for more info:
http://msdn.microsoft.com/en-us/library/ms750509.aspx
Another thing you could try would be rendering the vector art to a bitmap, and displaying that. Maybe it makes you feel icky to lose the vector precision, but if you know it's not going to change and it will look the same, what's the harm? (If you support printing or something that will require a hi-res version, you could always switch back for that operation.) For info on how to convert a UIElement to a bitmap, check out:
http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.rendertargetbitmap.aspx
Another possible solution: You don't really explain what kind of interaction you are doing with the elements, but if all you want to do is zoom and pan, a RenderTransform may be good enough (which is more efficient than a LayoutTransform and/or moving all the elements individually). I haven't played around with combining Freeze() and a RenderTransform, but you may be able to get the desired zooming while reducing the amount of layout WPF has to do.
I always use a Canvas when I'm laying out my visuals usually because I will need adjust the RenderTransform.TranslateTransform to animate in some way. A colleague recently told me that unless I explicitly need to animate I should always use the A Stackpanel because it is faster than a RenderTransform.TranslateTransform when laying out objects to the visual.
Is this true?
Anyone have any data either way?
I don't have any data on this, but if we're just talking about stacking then you using a TranslateTransform to achieve the exact positioning of each item seems extremely fragile since the item could theoretically be of different heights/widths which could also theoretically change dynamically at runtime not to mention if the designer changes them by hand they have to redo the translate transform for N other UI elements. Using StackPanel means the Measure/Arrange phases will occur and no matter what size the items are they will be laid out precisely.