Command CanExecute keeps firing in closed Popup

Jun 30, 2011 at 7:50 AM

Hi, I've been playing about with Cinch by trying to get a parent View going that opens a child popup View, but have noticed something odd with the child View's SimpleCommands that I'm hoping you can shed some light on.

It seems that after the childs ViewModel closes itself using "CloseActivePopUpCommand.Execute(True)" and returns back to the parent View, all of the 'CanExecute' handlers for the child ViewModel's SimpleCommands continue to fire (when change control focus etc in the parent view) even though it is now closed. This struck me as kinda strange so I did some searching and found that the child View needs to explicitly set its DataContext to Nothing in its Closed event (in the code-behind). Sure enough, this stopped the CanExecute handlers from firing after it was closed, but seems like a bit of hack to me and I'm worried there might be a memory leak occurring where the child ViewModel isn't being freed.

FYI, the code that shows the child View is:

 

Dim childVM As New ChildViewModel
_uiVisualizerService.ShowDialog("ChildView", childVM)

 

The child View's code-behind looks like:

<PopupNameToViewLookupKeyMetadata("ChildView", GetType(ChildView))> _
Public Class ChildView
    Inherits Window

    '*************************************************************
    'I'd rather not have to do this in every single Popup View...
    '*************************************************************
    Private Sub ChildView_Closed(sender As Object, e As System.EventArgs) Handles Me.Closed
        Me.DataContext = Nothing
    End Sub
End Class


The execute handler for the command in the child View that closes itself is:

Private Sub CloseCommand_Execute(args As EventToCommandArgs)
    CloseActivePopUpCommand.Execute(True)
End Sub

Has anyone seen this before and if so, why is it doing this and also do you know of any better solutions?

 

Thanks,

Shane

Jun 30, 2011 at 8:11 AM
Edited Jun 30, 2011 at 8:15 AM

Hello Shane,

you could modify the WPFUIVisualizerService.cs and modify the Closed EventHandler of the window and handle it there, so you don't need to add a handler in every view.

win.Closed += (s, e) => {
                win.DataContext = null;
                if (completedProc != null) {
                    completedProc(thisnew UICompletedEventArgs() {
                        State = dataContext,
                        Result = (isModal) ? win.DialogResult : null
                    });
                }
            };

I managed it the same way and it working great.
I believe it's because the WPFUIVisualizerService holds a referenze to the window in the anonym delegates. The MakeWeak call seems to not work in this szenario.
But as i saw the view got garbage colletable as a new view got oppened. So the memoryleak isn't that big.

Best regards,
Helmut

Jun 30, 2011 at 8:36 AM

Yep, that works nicely.

Thanks Helmut.

Jun 30, 2011 at 2:06 PM

Ah cool Helmut, I am just about to do another set of updates, so I will put this one in there too.

Jun 30, 2011 at 2:06 PM

shaneh20

 

Sorry only just saw this, Helmut has best answer, I'll put this into codebase soon