WPF View leak - invisible, but still rendered in the background - wpf

There is a complex App, I try to simplify the scenario. There is a host .exe (.NET), which contains lots of controls (ActiveX, .NET, WPF).
One control is basically a grid with items (call it "list"), and when new selection happens, it sends a message to another WPF control (call it "DataView"). "DataView" will display details of the current selection of "list". When DataView receives that message, it will re-create it's ViewModel, and assign to its DataContext, so re-create its View.
Its View is very complex (XAML declared), full of controls, templates, and also contains several Images (type: NonDPIImage, derived from Image, with a few basic non-important change, just consider it as Image), and it's Source is a Converter, which creates the BitmapImages.
<Image.Source>
<MultiBinding Converter="{StaticResource ImageConverter}">
...
It works fine, but I noticed that after selection changes the "DataView" update is getting slower and slower.
I debugged, and found that after several selection changes, all previous Views are still in the memory, and all are rendering its content, so the ImageConverter is called for all previous Views, thus it's getting slower and slower.
I tried to profile, this is what I see after 10+ selection.
You see the previous Views are still in the memory (lower prio problem), with the Images, and those are still being rendered (high prio problem), making the App slower and slower.
I am not really familiar with WPF, I read after leaks (mostly not DependencyProperty is used or similar), but this control is so difficult that first I wand to quickly workaround, so prevent rendering the leaked Views, and later on investigate the memory issue. (of course both would be the best...)
I tried that before DataContext assigned to new value, set the current View Image.Source to null, so at least the leaked Image will not render itself, but that caused the new View(!) also to lose its Image.Source, looks like WPF is caching or sharing like some static data?
As my first prio is to stop the "invisible render", after this I tried to set some of the model properties to null before creating the new one (so it would still leak, but at least no render anymore), so when Converter will receive properties to create the image, will see it's null, and skip the render.
But it behaves very strange!
For the leaked instances the breakpoint is not hit in the properties_get code, like as WPF cached the values or so?
This prevented me this path to continue.
Any help / idea would be appreciated guys.

Can you post your ImageConverter code?
the thing is creating an image from code and serving it as source for Image object,
can create strong link between them and memory leaks in scenarios like yours.
Try looking here:
https://stackoverflow.com/a/21878235/7722174

I think I found the issue: there was a message hook added to the View HwndSource (AddHook()) , but was not removed. This kept the whole View (see the red rectangled class) alive.
Now if I call MyHwndSource.RemoveHook(WndProc) in the UserControl_Unloaded, the View will be also GCd.

Related

WPF Printing multiple pages from a single View Model

I am currently a little bit troubled by the following problem. I have a user interface which basically shows a graphic (a canvas made of Lines, Circles, ... these are all WPF objects). Depending on the selection a user makes in the menu, some items get deleted and some get added. So the basic image looks the same, but a few modifications are made.
The user has the possibility to select - say - 10 different "pages" by clicking a Next/Previous Button.
I am using MVVM Light and my ViewModel contains all the items of the graphic (all Lines, ...).
Now I would like to print that graphic to multiple pages. The first page should contain the graphic with changes from page 1, the second page contains the graphic with changes from page 2 and so on. The actual number of pages is dynamic. I track this with a property CurrentPage and a property PagesTotal.
Whenever I push the "Next" button, this causes a command to be executed which will change the variable CurrentPage and also makes sure that the correct items are displayed.
Now I would like to print this but this is where I'm stuck. I dont' mind leaving the MVVM zone and doing some dirty work in code-behind but I would refuse to draw everything again like in the old GDI days.
Any ideas are really welcome.
Create a UserControl containing your display logic (you graphic, for instance). Grab you ViewModel list and project then in UserControls, setting each ViewModel as each UserControl's DataContext.
Force each one to render calling Measure with infinite value and then Arrange with the resulting DesiredHeight and Width. Then follow the procedures to print WPF visuals (link link link).
Essentially, this should be quite simple if and only if your views work independently; i.e. your ViewModel doesn't contain UiElements that are placed into your View.
Simple solution is to basically print your visual root. If need be encapsulate your Views in a user control first.
PrintDialog printDlg = new PrintDialog();
UserControl1 uc = new UserControl1();
printDlg.PrintVisual(uc, "User Control Printing.");
Reference
Alright, I have to admin that I now switched back to doing the printing through code only. I would have really liked doing it "WPF-style" but handling the multiple pages issue was just too much trouble.
Anyway, there is still one issue regarding the printout left but this will be another question.

Memory leak and performance issue with WPF's TreeView

I'm running into a problem with the WPF TreeView control.
I think I ran into a memory leak issue with this control and also some performance issues.
I've prepared a simple demo solution where you can see these problems.
Download link: http://www.custom-projects.com/TreeViewMemoryAndPerformanceIssue.zip
I'm creating the tree based on some domain objects. The objects are wrapped in view models.
The number of levels is not restricted, but currently we have a maximum of 3 levels.
So, each view model can have children.
When you click on the up/down buttons of the UpDown control and don't release the mouse button you will see, that the update speed of the int value will get slower and slower and the memory consumption constantly rises.
What I'm doing: When you click on the up/down button the value is sent to the view model via data binding. In the setter I'm raising a event. Our application consists of different view models and if someone is changing data in one of them, the others are notified through these DataChanged events.
For simplicity, my demo solutions just consists of the NavigationViewModel. So it listens
for the DataChanged event and if fired, the tree is rendered.
Because we don't have a list which will always be the same (and just rows are added or removed), I'm not using a ObservableCollection. We always have to regenerate the list based on the objects the user has added/created.
Anyways, I'm adding these view models to a list and raise the NotifyPropertyChanged event
so that WPF updates the tree. Works well but the more the list is updated, the slower the application gets (and memory goes up).
I checked, that the item view models are garbage collected and they are, so I don't see
something wrong on my side. I also did some performance profiling. It looks, that the
issue is on the WPF side, because my code does not slow down. The Application.Run method
execution time rises... Strange thing.
Does anyone has an idea, why the memory is going up and never gets released and why the
performance starts to decrease the more often the TreeView updates itself?
I would appreciate any help or comment on this issue.
Thanks,
Christian
I profiled your test application using ANTS Memory Profiler and you can see that your classes 'NavigationItemBaseViewModel' and the array "NavigationItemBaseViewModel[]" are still held in memory by references, and this is getting worse with each increment.
If you slowly increment and allow the update to happen, then the references are broken and objects disposed. All good.
However, if you increment fast/continuously then you see that your references are not broken, thus the arrays are kept in memory.
The increments get slower each time because your application is having to update a lot of these view models, at increment #58 I had 172 arrays holding between them 517 NavigationItemBaseViewModel's.
Where with "normal" functionality you only have 4 arrays and 13 NavigationItemBaseViewModel's.
Hope that helps, I would recommend you profile your memory if you cannot figure out your logic where new are creating new arrays. Typically it is best to reuse arrays.
Profiler I used is here: http://www.red-gate.com/products/dotnet-development/ants-memory-profiler/index2
Hope that helps.
I was investigating lots of memory leaks in WPF and i find this tool very useful: http://www.jetbrains.com/profiler/ It has trial period of 10 days (i've just checked) so i hope you will be able to find your problem.

does the wpf datagrid have a virtual mode like the winforms DataGridView?

The winforms DataGridView has a virtual model and uses the OnCellValueNeeded method to gets cell values from a a user defined data store.
How do i do this in wpf? The DataGrid doesn't seems to have a OnCellValueNeeded method.
Thanks
Not sure if this already helps you:
DataGrid uses UI virtualization, what means that objects are not created before they are visible on screen and the corresponding properties of your source objects will not be called as long as they are not visible. It means also that ui-elements are recycled after they are no more visible.
This is for free and you don't have to do additional coding to use this feature. If I interprete your question right, the main question is, how to know that a property of a business-object is needed. For UI-virtualization, this is when the property is called the first time - You can do some lazy initialization. But beware to put too heavy initialization code into the properties (DB synchronous lookups etc), otherwise your DataGrid will become very slow and unhandy.

Should Silverlight Controls be re-loaded onto pages?

Some months ago I started developing a Silverlight application on my own. I quickly discovered that I was unable to get expected garbage collection for most of my controls. I struggled for about a week with WinDBG and ANTS memory profiler and then found the "DataTemplate memory leak" strand on the Silverlight forum (http://forums.silverlight.net/forums/t/171739.aspx).
Given that so many people seemed to be frustrated with various memory issues I decided to delay further investigation into the memory situation until the most obvious issue was resolved.
Anyway, now I'm looking into the issue again and I realise that the problem I'm having is much more fundamental than I had first thought. I simply don't have a paradigm for writing garbage collectable Silverlight controls when: a) the control has dependency properties that can be bound to, and b) the control can be unloaded from one control and then subsequently loaded again.
I'm starting to think that the second of these demands is too great. Can anyone confirm this?
To give a tiny bit more detail, the most robust pattern I can come up with for writing good, garbage collectable Silverlight controls is as follows:
1) When a Control's Template is applied (in the OnApplyTemplate override) I setup any internal bindings between local properties and TemplateParts. For example, I might setup a Binding between a local property called CanSearch and a button.
if (x_Button_Search != null)
{
Binding b = new Binding("CanSearch");
b.Source = this;
this.x_Button_Search.SetBinding(Button.IsEnabledProperty, b);
}
2) When the Control raises the Unloaded event, I clear the internal bindings and un-wire any eventhandlers.
if (x_Button_Search != null)
{
this.x_Button_Search.ClearValue(Button.IsEnabledProperty);
}
This seems to be the cleanest way of ensuring that no trailing references exist between the x_Button_Search element and the Control. I don't know if this is strictly necessary.
3) Again, when the Control raises the Unloaded event, I clear bindings to existing dependency properties.
this.ClearValue(SearchParametersProperty);
If I fail to do this I can cause leaks. For example, if the SearchParameters property was bound to some INotifyPropertyChanged object then a reference to the Control remains in the PropertyChanged event on the INotifyPropertyChanged object to which I am bound even after the control has been unloaded i.e. the View will stay around as long as the Model and that may not be desired.
4) I 'flicker' the Template value so that next time the control is loaded, the template is reapplied and the OnApplyTemplate method is fired again.
var oldTemplate = this.Template;
this.Template = null;
this.Template = oldTemplate;
The reason to do 4 is that I need to reinstate bindings when the Control is reloaded onto a page. In Silverlight, there are two points of entry through which to do this: in the OnApplyTemplate override or after the control fires the Loaded event. As I want to enforce binding values before the control has been loaded (to avoid flickering), there is only one available entry point available, OnApplyTemplate. I have to flicker the template in order to force the template to reapply when the control is reloaded.
It appears this pattern up to point 3 is the bare minimum for providing garbage collected controls.
My problem comes when you want to unload your control (remove it from a Panel for example) and subsequently reload it. Any dependency properties on the control have been set to null in point 3. For example, imagine there is a binding on the declaration of the control e.g. . As far as I can tell, there is no way of reinstating this Binding once the value of SearchParameters has been set to null, it's not part of a Template after all. The result is that when the control is re-loaded it's as if the value of SearchParameters was null. So I either skip out step 3 in the pattern and get a reloadable control that is not garbage collected, or I keep 3 and get an unreloadable control.
What you do in 1) seems really strange. Why initiating a binding to the template in code and not in xaml?
We have solved lots of memory leak issues in silverlight using this software
http://memprofiler.com/
EDIT
For more control over the binding, you can use
{Binding Property, RelativeSource={RelativeSource TemplatedParent}}
That way the implicit converters are used as expected and you can also specify your own. And I believe that BindingMode TwoWay works as well.
Good luck!

WPF How to erase a DrawingVisual with RemoveVisualChild

Using WPF I'm drawing symbols in the "fast way" (Drawing rendered on DrawingVisuals, no Shapes). So... I can successfully draw them and get hit-tested with no problem.
But when trying to remove them, using RemoveVisualChild() plus RemoveLogicalChild(), there is no effect on the screen: No visual removing.
I'm implementing my own displaying canvas-alike object (overriding VisualChildrenCount, GetVisualChild, MeasureOverride and ArrangeOverride).
For a while I believed it was a problem of refresh, but after invoking many methods (InvalidateMeasure, InvalidateArrange, InvalidateViual and UpdateLayout, plus a Dispatcher calling technique for post background-threading execution) well... the supposedly erased objects are still there.
A curious thing is that new objects going to be drawn OVER these erased ones, are in fact rendered UNDER them!!
Any Ideas?
SOLVED: It was my mistake (what a shame!)... A recursive symbol update, started at property setter level, was repainting the object.

Resources