WorkItemController/View oddity

Topics: CAB & Smart Client Software Factory
Jun 18, 2007 at 3:30 PM
I'm burning up the boards lately, but I have another question. It seems that workitems/views aren't being destroyed properly, even though I've ensured that the terminated and disposed events are firing properly. I have workitemcontroller a open workitemcontroller b, which opens workitemcontroller c. If I move to a different record in workitemcontroller a and open workitemcontroller b and then workitemcontroller c, when closing workitemcontroller c, it must be closed twice and fires terminated and disposed twice. If I then move to a different record in workitemcontroller a and go through the same steps, workitemcontroller c must be closed 3 times. If I repeat, it continues to increment. If ayone has a clue what is going on, I would appreciate your insights.

In the view (C), I've coded OnCloseView as follows (testing forcing termination of the workitem associated with the view)

Public Sub OnCloseView()
MyBase.CloseView()
WorkItem.Items.Remove(View)
If TypeOf View Is IDisposable Then
CType(View, IDisposable).Dispose()
End If
Me.WorkItem.Terminate()
End Sub

The code (slightly modified to check for terminated and disposed) is as follows for WorkItemControllerB and C.

(WorkItemControllerB)
Imports System
Imports System.Windows.Forms
Imports Microsoft.Practices.CompositeUI
Imports Microsoft.Practices.CompositeUI.Commands
Imports SCBDCM.Infrastructure.Interface
Imports Microsoft.Practices.CompositeUI.EventBroker
Imports SCBDCM.ContactsModule.Constants
Imports ScottTest.BusinessObjects
Imports CompositeUIExtensions.State
Imports Microsoft.Practices.CompositeUI.Utility

<InheritState("Contact")> _
Public Class ContactWorkItemController
Inherits WorkItemController

Private WithEvents test As ControlledWorkItem(Of AddressWorkItemController)

Private Sub AddViews()
Dim view As ContactsDetailView = Me.WorkItem.SmartParts.AddNew(Of ContactsDetailView)()
Me.WorkItem.Workspaces(Constants.WorkspaceNames.RightWorkspace).Show(view)
End Sub

<EventSubscription(EventTopicNames.EditContactAddress, ThreadOption.UserInterface)> _
Public Sub OnEditContactAddress(ByVal sender As System.Object, ByVal eventArgs As DataEventArgs(Of Addresses))
WorkItem.State("Address") = eventArgs.Data
test = WorkItem.WorkItems.AddNew(Of ControlledWorkItem(Of AddressWorkItemController))()
test.Controller.Run()
End Sub

<EventSubscription(EventTopicNames.AddContactAddress, ThreadOption.UserInterface)> _
Public Sub OnAddContactAddress(ByVal sender As System.Object, ByVal eventArgs As DataEventArgs(Of Addresses))
OnEditContactAddress(sender, eventArgs)
End Sub

Public Overrides Sub Run()
MyBase.Run()
AddViews()
End Sub

Private Sub testsub(ByVal sender As System.Object, ByVal eventArgs As EventArgs) Handles test.Terminated
MsgBox("WorkItem.Terminated")
End Sub

Private Sub testdispose(ByVal sender As System.Object, ByVal eventArgs As EventArgs) Handles test.Disposed
MsgBox("WorkItem.Disposed")
End Sub

End Class

(WorkItemControllerC)
Imports System
Imports System.Windows.Forms
Imports Microsoft.Practices.CompositeUI
Imports Microsoft.Practices.CompositeUI.Commands
Imports SCBDCM.Infrastructure.Interface
Imports Microsoft.Practices.CompositeUI.EventBroker
Imports SCBDCM.ContactsModule.Constants
Imports ScottTest.BusinessObjects
Imports CompositeUIExtensions.State

<InheritState("Contact", "Address")> _
Public Class AddressWorkItemController
Inherits WorkItemController

Public Overrides Sub Run()
MyBase.Run()
AddViews()
End Sub

Private Sub AddViews()
Dim view As AddressesDetailView = WorkItem.SmartParts.AddNew(Of AddressesDetailView)()
WorkItem.Workspaces(Constants.WorkspaceNames.RightWorkspace).Show(view)
End Sub

End Class

Jun 18, 2007 at 3:50 PM
This migth be a blind shot, but instead of using withevents for the test WorkItemController dim it up without using withevents and hook up the event handlers with AddHandler and RemoveHandler instead.
Jun 18, 2007 at 3:56 PM
Initially, the code for WorkItemControllerB was as follows. I just used the private variable withevents so I could see that it was, in fact, being destroyed.

Imports System
Imports System.Windows.Forms
Imports Microsoft.Practices.CompositeUI
Imports Microsoft.Practices.CompositeUI.Commands
Imports SCBDCM.Infrastructure.Interface
Imports Microsoft.Practices.CompositeUI.EventBroker
Imports SCBDCM.ContactsModule.Constants
Imports ScottTest.BusinessObjects
Imports CompositeUIExtensions.State
Imports Microsoft.Practices.CompositeUI.Utility

<InheritState("Contact")> _
Public Class ContactWorkItemController
Inherits WorkItemController

Private Sub AddViews()
Dim view As ContactsDetailView = Me.WorkItem.SmartParts.AddNew(Of ContactsDetailView)()
Me.WorkItem.Workspaces(Constants.WorkspaceNames.RightWorkspace).Show(view)
End Sub

<EventSubscription(EventTopicNames.EditContactAddress, ThreadOption.UserInterface)> _
Public Sub OnEditContactAddress(ByVal sender As System.Object, ByVal eventArgs As DataEventArgs(Of Addresses))
WorkItem.State("Address") = eventArgs.Data
Dim item As ControlledWorkItem(Of AddressWorkItemController) = WorkItem.WorkItems.AddNew(Of ControlledWorkItem(Of AddressWorkItemController))()
item.Controller.Run()
End Sub

<EventSubscription(EventTopicNames.AddContactAddress, ThreadOption.UserInterface)> _
Public Sub OnAddContactAddress(ByVal sender As System.Object, ByVal eventArgs As DataEventArgs(Of Addresses))
OnEditContactAddress(sender, eventArgs)
End Sub

Public Overrides Sub Run()
MyBase.Run()
AddViews()
End Sub

End Class
Jun 18, 2007 at 5:42 PM
As an update to this, it duplicates any ViewC. For example, if I edit a detail record's email address, phone number, address, note, etc, (other event subscriptions in the ContactWorkItemController) when switching to a different record, any of the detail edit screens will be duplicated. So, if I edit a phone number for one record, when switching to a different record, if I edit an email address, I will have to click save or cancel twice. It appears to be something with the ControlledWorkItem.WorkItems collection, but I'm not sure exactly what the deal is. Since the objects are being terminated/disposed, they should be removed from the ControlledWorkItem.WorkItems collection. It's almost like it looks at the count and/or does a for each on it. Surely someone has run into this before.
Jun 18, 2007 at 5:54 PM
I figured this out (or at least a workaround). I changed the OnCloseView method in WorkItemControllerB (ContactWorkItemController above) to terminate its workitem on closing and the problem seems to have gone away...

Public Sub OnCloseView()
MyBase.CloseView()
Me.WorkItem.Terminate()
End Sub
Jun 18, 2007 at 6:00 PM
Whoops. I actually changed the code in the view's (loaded in WorkItemControllerB.AddViews) associated presenter (in this case ContactsDetailViewPresenter). Hope this helps someone else...