1
votes

I've run across an issue when I close a popup created with Caliburn micro : The view doesn't seem to be destroyed.

I use Caliburn.Micro 2.0.1 with MEF, you can see my exemple here : https://github.com/louisfish/BaseCaliburn

Basically, I create a window with a button inside. When you click on this button, a new window is opened with the ShowWindow function of WindowManager. In this popup, I created a message with a binding. I put output traces when my message is get in my ViewModel.

using Caliburn.Micro;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BaseCaliburn.ViewModels
{
    [Export]
    public class PopupViewModel : Screen
    {
        private int _timesOpened;
        private string _message;
        public string Message
        {
            get 
            {
                Debug.WriteLine("Message is get");
                return _message; 
            }
            set
            {
                if (value == _message) return;
                _message = value;
                NotifyOfPropertyChange(() => Message);
            }
        }
        protected override void OnActivate()
        {
            Debug.WriteLine("---Window is activated---");
            _timesOpened++;

            Message = "Popup number : " + _timesOpened;
        }      
    }
}

Each time I open and close my window, the old binding stays there. So after 5 open/close, I have 5 call to my get Message in my ViewModel.

So I receive the binding of the old views:

Message is get
---Window is activated---
Message is get
Message is get
Message is get
Message is get
Message is get
1
2 things possible, 1) you are not calling TryClose(true) on closure of your popupview, this should close the viewmodel and "kill it", and since you are using MEF, there is [PartCreationPolicy(CreationPolicy.NonShared), by default MEF creates all parts with PartCreationPolicy = Shared which equivalent to "Singleton"mvermef
I tried adding [PartCreationPolicy(CreationPolicy.NonShared)] to my PopupViewModel and the behavior is the same.Louis Fish

1 Answers

1
votes
  • You have one single instance of HomeViewModel. You're having your main window bound to the HomeViewModel, so every time you click StartApp, the method is called on the same instance.
  • This instance has a PopupViewModel property, which is initialized by your dependency injection container as soon as the HomeViewModel gets created. Then, it stays the same. Every time your StartApp method gets the value of the property, the same instance of PopupViewModel is returned.
  • What you actually want is a new PopupViewModel instance every time you call StartApp. You need a factory. In MEF, you can import ExportFactory<T> to create instances on demand:

    [Import]
    public ExportFactory<PopupViewModel> PopupViewModelFactory { get; set; }
    
    public void StartApp()
    {
        Application.Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
    
        PopupViewModel newPopup = this.PopupViewModelFactory.CreateExport().Value;
        IoC.Get<IWindowManager>().ShowWindow(newPopup);
    }