Get window size without degrading performance - wpf

My WPF program sometimes needs the size of the window. The simplest solution is to bind the ActualWith and ActualHight. But how is the performance when doing so? Is the Height and Width updated repeatedly each time I resize the window?
Is there any way to get the size only when I need it?

As always, when you are worried about performance: test.
Binding to the ActualHeight and ActualWidth might be not so bad because the Window might not change that much/many times.
The only (proper) way to connect the ViewModel to the View is by using a binding. If this is too costly you could add two extra properties to the Window/View that only update (using a resize event for instance) when this is relevant to you. You could then bind the ViewModel to those.
My bet is that your application contains other things that need more attention ;)

Related

Event that fires after element is resized

Here is a problem: after loading some visual elements, I need to change something knowing their new sizes. There is MeasureOverride method, but it is called before changing the size. Is there any method that is called after it?
P.S. I know that I can calculate new sizes having old ones, but new sizes aren't calculated simply. It would be much easier to just use such an event (if it exists).
Are you looking for the FrameworkElement.SizeChanged event?
MSDN's description:
Occurs when either the ActualHeight or the ActualWidth properties change value on a FrameworkElement.
EDIT:
This article has a good description of both the SizeChanged and LayoutUpdated events, including an overview of how the layout loop works.

WPF - Virtualising WrapPanel

does anyone have a functioning virtualising WrapPanel I can use in a WPF application?
I have downloaded and tried the implementation at http://virtualwrappanel.codeplex.com/. However, I get the following exception:
"Layout measurement override of element 'MyNamespace.VirtualizingWrapPanel' should not return PositiveInfinity as its DesiredSize, even if Infinity is passed in as available size."
This is when trying to apply the wrappanel to a ListBox
This is probably a bug that you might be able to fix yourself. Look for the MeasureOverride method. It always seem to return the availableSize wich was passed to the method. As the exception states you must not return availableSize when it contains double.PositiveInfinity. So try this:
if(availableSize.Width == double.PositiveInfinity || availableSize.Height == double.PositiveInfinity)
{
return Size.Empty;
}
// all the measureoverride code comes here
return availableSize;
I haven't looked at the implementation in details. But who knows, you might be able to get a away with this if the panel doesn't save state between MeasureOverride and ArrangeOverride (wich it shouldn't if it is well implemented).
That problem is probably occuring because you have your listbox inside another control, such as a stack panel or scroll viewer, which allows the listbox to grow to whatever size it likes. While the virtual wrap panel shouldn't give an error in this case, it does explain the performance problem.
Even using one of Microsoft's own virtualising panels won't fix the performance issues in this case because the virtualisation is defeated. Since the listbox can grow to whatever size it likes, it does so and draws all the items even if they're not on screen... hence the virtualisation doesn't apply.
If you ensure your listbox isn't inside one of these sorts of containers, you should find the virtualisation starts working performance improves significantly.

Tweak WPF application performance which hosts hundreds of similar controls

We just ported our WinForms application to WPF.
However, performance decreased dramatically.
We have a User Interface which consists of about 200 UserControl.
Each UserControl is defined by a DataGrid (= 10 columns and 3-15 rows) as well as a Panel which hosts about 10 Buttons.
They are all hosted in a ScrollViewer.
(Please don't recommend to change the UI. I don't have any influence on that. The customer wants to be able to scroll to any of those UserControls.)
Since we ported the whole application to WPF the startup time increased by 100%. Using WinForms we experienced startup times of 15sec whereas now, we are struggeling with 30s.
Do you have any recommandations or ideas how to improve the loading time of a UI which consists of identical UserControl where simply each UserControl is bound to a different ViewModel? (Maybe some fast cloning of the UserControl instances or sth similar?)
I am using static Resources whereever possible.
I avoid Grids and Auto Sizing whereever possible.
Hope someone can share some thoughts on that one.
Thanks,
TH
First find out what is responsible for the time.
Maybe it's the controls, and maybe not. Often it's data structure.
I use the random-pause method.
My final solution is a custom Virtual Panel which supports items of dynamic height.
See http://rhnatiuk.wordpress.com/2006/12/13/implementing-a-virtualized-panel-in-wpf/ on how to create virtual panels.
My UserControls support two states:
- Initial
- Loaded
When the application is in idle the virtual Panel asks the Controls to change to the "Loaded" state. This loads the expensive UserControl.
Like that everything is lazy loaded and as soon as the user stops scrolling the visible items are loaded.
Maybe that helps others that are in the same sitaution.
TH
Try only to create the controls which are visible at the time, use lazy loading.
Maybe SnapsToDevicePixels=true can also help a little bit.
Guys, I thought about the following implementation. If anyone has concerns please let me know:
I will implement my own virtualizing "StackPanel" which supports smooth scrolling.
For the moment we assume that the height of my UserControls is fixed. One page could possibly hold 5 UserControls.
I will then go ahead and cache the preceding as well as the proceeding page:
In memory I will always hold 15 UserControls.
The content of the ScrollViewer is a Canvas.
Locations of my UserControls are adjusted by setting Canvas.Top.
Let's say the current situation is the following:
User has scrolled to page 2.
That means UserControl 5-9 is visible. Now the user scrolls down.
As soon as UserControl 5 becomes invisible I take the UC of the top (in this case UserControl 0), change its ViewModel and adjust its Canvas.Top so that it now is the Control which is at the End of the ControlCollection.
If the user scrolls any further I take UC 1, change its ViewModel and adjust its Canvas.Top.
And so on.
Furthermore I will set Canvas.Height manually so that the ScrollViewer represents the ScrollBars in a correct way.
I hope my explanation is understandable :)
What do you think?
BR,
TH
I remember reading something about how each instance of a UserControl loads the resource dictionary. So if you have as many of these as you describe it can take a while to load those.
Unfortunately I can't find the link I remember, but here is one that might help:
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/c9b6aa9f-5a97-428c-8009-5cda432b820c
Another thing to try is to not use UserControls and instead use a DataTemplate to build your datagrids and buttons. Or make a custom control template for the datagrid that includes the buttons. Either one might be faster.
Hope this helps.

Silverlight PRISM getting the rendersize of a region

I am trying to get the render size of a region via the region manager. The reason for this is each time I add a view to the region I want to make sure it will visually fit, I can get the dimensions of the view I am about to add but I am struggling to find a way of getting the height of the region I am about to add to.
Obviously I want to stay away from the view behind code and accessing the UIElement for the region directly.
Any ideas?
Thanks for your time
I'd recommend against trying to do this at all. Instead, I would focus on making the region adaptable to being overfilled (automatic resizing, scrolling, tabs, etc).
There's a lot of unpredictable things that can happen here. For example, there are some controls whose views are determined by their container. The true size of the view that you want to add to the region will not be known until it's actually added to the region, so making this decision will be non-trivial.
I know this doesn't directly answer your question, but hopefully it will be helpful regardless.
You can use
_regionManager.Regions[regionName].Views.ElementAtOrDefault(0);
to get the current view of the region you want to use.
Then you can check the DesiredSize property of that view to see what the probable width and height is of that region.
I think this should work in normal usage.
The thing is there always needs to be a view in that region. If there isn't you might want to use a dummy view or so.

Dynamic animations, Commands and separation of concerns

Scenario: I have a (numeric) textbox, a button, and a label. When the button is clicked I'd like the label to "animate" to the numeric value in the textbox (like a spinning dial)
Given:
a) that animations in storyboards cannot have databindings (because they are not FrameworkElements)
b) the lack of triggers in Silverlight
What is the best, and with least coupling of the view model to the view's storyboard, way to update the target animation value and start the animation when the button is clicked?
Note: The scenario is conceptual, so don't concentrate on the specifics of 'animating' numbers or anything
If your goal is strictly to reduce the code-behind in the view I think that an attached behaviour on the Label would work for this. The attached behaviour on the label would expose the number to be animated to and when this number changes an animation (in code) would be run to animate from the old value to the new value.
One drawback is that your animation is now in code, unless you store a templated (just has fake values to start with) version of it in a resource file somewhere where you can load it as needed and replace the templated values.
This article from Josh Smith seems to be the authority on Attached Behaviours;
http://joshsmithonwpf.wordpress.com/2008/08/30/introduction-to-attached-behaviors/
I recently had to solve a similar problem in an MVVM application. My problem was that I needed to animate a container's height from zero to auto. Since Auto is a dynamic value I recognized that the animation (or storyboard) would need to be built (or manipulated) on demand. The solution that I put in place involved using view code-behind to update and fire the animation.
This isn't the most MVVM-friendly approach; however, animations in WPF can be tricky in XAML. Since this solution is really just a workaround for a XAML limitation it seems okay to tie the code directly to the view. Likewise, if the views were mocked then there would be no framework elements to animate, so it really wouldn't make sense to place this code on the VM side.
Does anybody have a better approach?

Resources