Egor4eg
Egor4eg

Reputation: 2708

Do not call CanExecute methods from hidden windows

I use MVVM pattern in my WPF application. I'm trying to cache my windows in order to increase performance. To do that I never close them and just hide instead of closing. All hidden windows are stored in a dictionary, so I can re-use them. When window is opened again I create a new view model and associate it with a cached view.

But there is a problem with that because hidden window keep invoking of CanExecute methods of commands in ViewModels. This leads to performance issues when user opened and closed a lot of windows.

When I set Window.DataContext property to null or do ClearValue(DataContextProperty) I achieve my goal, but there is a problem with that. If I have any two way bindings, they all fired during unbinding from data context. So, some values in my view model become null. I do not want that because in some cases I read properties from ViewModels after hidding of Views.

Can you help me to resolve the main problem (do not call CanExecute methods from hidden windows).

Upvotes: 1

Views: 209

Answers (1)

mclark1129
mclark1129

Reputation: 7592

I don't think you get much control over when and where the CommandManager decides to fire off a RequerySuggested event. One way you may be able to mitigate the performance hit would be to have a property on your ViewModel that allows you supress execution of CanExecute. Whenever a View that a ViewModel is bound to goes into hiding, then you can set this property to True

A simple example

// Called when a view goes into hiding
myViewModel.SuppressCommandRequery = True

In your CanExecute handler(s) simply place this line at the beginning of the method

public bool CanExecuteCommand(Object parameter) {

    if (this.SuppressCommandRequery) 
        return;

    // Continue processing the event...
}

I would point out that you need to take special care to then disable the suppression whenever the view came out of hiding. However, in the cases where re-displaying the View results in a new instance of the ViewModel this would not be necessary.

Alternatively, take a look at this question which talks about using an implementation of a DeletegateCommand from the Prism MVVM Framework. I haven't used this myself, but it looks like it may address some of your concerns.

Upvotes: 2

Related Questions