I recently found out that my Handle() method was called multiple times after a single publish... and discovered that deactivated and closed ViewModel instances were actually not disposed of and kept receiving messages ! I'm looking for a way to either properly dispose of obsolete viewmodels or simply remove them from EventAggregator subscription.
My shell is a
Conductor<T>.Collection.OneActive, IScreenEx where T : class, IScreenEx
The conducted items are registered with SimpleContainer as follow:
container.PerRequest<ILinkageMovements, LinkageGraphViewModel>();
and activated like this:
public X SwitchToNamed<X>(String key) where X : T
{
var existing = Items.FirstOrDefault(y => y.GetType() == typeof(X) && y.UniqueKey == key);
if (existing == null)
existing = Items.FirstOrDefault(x => x.GetType().GetInterfaces().Contains(typeof(X)) && x.UniqueKey == key);
if (existing != null)
{
ChangeActiveItem(existing, false);
return (X)existing;
}
else
{
X vm = container.GetInstance<X>();
vm.UniqueKey = key;
ActivateItem(vm);
return vm;
}
}
And the ViewModel is constructed this way:
public LinkageGraphViewModel
(
Caliburn.Micro.SimpleContainer container,
Caliburn.Micro.IEventAggregator eventAggregator,
IDialogManager dialogs,
IDataService dataService,
IReferentialData refData
)
: base(container, eventAggregator, dialogs, dataService, refData)
{
DisplayName = Strings.Movements;
}
Finally the very base class constructor is:
public BaseConductor(SimpleContainer container, IEventAggregator eventAggregator, IDialogManager dialogs)
{
this.container = container;
this.eventAggregator = eventAggregator;
this.eventAggregator.Subscribe(this);
this.Dialogs = dialogs;
}
Please help.
There is an
Unsubscribe
method onIEventAggregator
interface.The answer the question about when it's a good time to call it depends on your architecture - the code you posted does not explain when your view models are not needed anymore - they might stay in Items forever.
Normally you'd subscribe in
OnActivate
and unsubscribe inOnDeactivate
however your code subscribes in the constructor so I guess you might want inactive models to be subscribed soCanClose
might be another candidate.