views:

125

answers:

2

Hi,

I have a quite simple scenario that I cannot get to work correctly. I have 2 views, CarView and CarWindowView (childwindow) with corresponding ViewModels. In my CarView I have an EditButton that that opens CarWindowView (childwindow) where I can edit the Car object fields.

My problem is that the DisplayModule method in my CarWindowView ViewModel is getting called too many times...When I push the edit button first time its getting called once, the second time its getting called twince, the third time its getting called 3 times and so fort... !

CarView ViewModel constructor:

Public Sub New(ByVal eventAggregator As IEventAggregator, ByVal con As IUnityContainer, ByVal mgr As ICarManager, ByVal CarService As ICarService)

    _Container = con
    _CarManager = mgr
    _EventAggregator = eventAggregator

    'Create the DelegateCommands
    NewBtnClick = New DelegateCommand(Of Object)(AddressOf HandleNewCarBtnClick)
    EditBtnClick = New DelegateCommand(Of Object)(AddressOf HandleEditCarBtnClick)
End Sub

CarView ViewModel HandleEditCarBtnClick method:

Private Sub HandleEditCarBtnClick()

    Dim view = New CarWindowView
    Dim viewModel = _Container.Resolve(Of CarWindowViewModel)()
    viewModel.CurrentDomainContext = DomainContext

    viewModel.CurrentItem = CurrentItem
    viewModel.IsEnabled = False

    view.ApplyModel(viewModel)
    view.Show()

    _EventAggregator.GetEvent(Of CarCollectionEvent)().Publish(EditObject)
End Sub

CarWindowView ViewModel constructor:

Public Sub New(ByVal eventAggregator As IEventAggregator, ByVal con As IUnityContainer, ByVal mgr As ICarManager, ByVal CarService As ICarService)

    _Container = con
    _CarManager = mgr
    _EventAggregator = eventAggregator

    _EventAggregator.GetEvent(Of CarCollectionEvent).Subscribe(AddressOf DisplayModule)

End Sub

CarWindowView ViewModel DisplayModule method (this is the method getting called too many times):

Public Sub DisplayModule(ByVal param As String)
If param = EditObject Then
  IsInEditMode = True
  ' Logic removed for display reasons here. This logic breaks because it's called too    many times.
  End If
End Sub

So, I cannot understand how I can only have the EventAggregator to store just the one single click, and not all my click on the Edit button. Sorry if this is not to well explained! Help appreciated!!

+2  A: 

It sounds like you have a memory leak of CarWindowViewModel. In other words, you have multiple instances of that class that have not been garbage collected. In the debugger, look at GetHashCode. I'm willing to bet that they are different.

Assuming you are using the EventAggregator from Prism, it is supposed to keep a weak reference to your object, so that is not your problem.

Most likely, you need to ensure that when that ViewModel is done, it unsubscribes from the event. Also, see if you can figure out what in the referance chain is keeping them alive.

Brian Genisio
You might very well be correct,I will investigate.What do you mean with; "In the debugger, look at GetHashCode" - what is GetHashCode and how can I look at it during debugging?Also I'm running this line of code on each EditBtn click: _Container.Resolve(Of CarWindowViewModel)() Can that cause the behaviour?
Mcad001
When you are in the debugger in a method of the class, type this.GetHashCode() into the watch window. It will give you a unique ID for your class. Using this, you can find out which instance you are looking at. A similar mechanism is to add this to the watch window and choose "Make ID", and it will give it a more pretty ID to track it by.If you are using a container to resolve the ViewModel, you might consider configuring it as a single lifetime... that way it only gets created once.Look for events that you are hooking in the class. It is a common place for leaks.
Brian Genisio
You were correct Brian.Unsubscribing the event fixed my problem.
Mcad001
+1  A: 

I consider EventAggregator events to be those that you want any old view or viewmodel written in other modules to listen to (or not, as they please). In the case that I have two views that are very dependent on each other to operate and they always live in the same logical tree, I use regular old .NET events.

It's only the "fire and forget" type of events that I feel are appropriate for the EventAggregator. I know the samples in the Prism package seem to advocate their use in more tightly coupled master/detail scenarios, but I don't really think that appropriate (read: overkill).

Although this doesn't directly address your issue (I'm of the mind that you have a memory leak as well), if you organize it like this you'll likely avoid this issue altogether.

Anderson Imes