Search code examples
mvvmsilverlight-4.0mefdisposechildwindow

Silverlight ChildWindow not disposed using MEF and MVVM


I'm not sure if what I'm experiencing is the same as here: Silverlight ChildWindow Memory Leak but...:

I've got a Silverlight ChildWindow with 3 radio buttons in the same group with IsChecked all set to false in XAML, I don't want any of them selected upon opening. I open up the ChildWindow from my viewmodel:

if (_NewChildWindowCommand == null)
    _NewChildWindowCommand = new RelayCommand(param => _cwService.ShowDialog(_newLocation, new NewViewModel(), closed =>
      {
          if (_newLocation.DialogResult.HasValue && _newLocation.DialogResult.Value)
          {
              //do something
          }
          _newLocation = null;
           _newLocation = _container.GetExportedValue<INewChildWindow>();
      }));

I then select one of the radio buttons hit OK. It Closes, I open it up again and the ChildWindow seems to have been disposed since upon opening, none of those radio buttons are selected (the way it should be). So I select a radio button again,hit OK, It Closes...But the third time I open the ChildWindow, it has the same radio button selected as when I closed it. This is what I don't understand. I thought by setting _newLocation=null like I did and then getting INewChildWindow from the container would give me a new ChildWindow but it doesn't seem to be the case. I tried calling GC.Collect() after setting _newLocation to null but that didn't work, and I tried setting the PartCreationPolicy to NonShared on the ChildWindow, however that doesn't make a difference since the instance of the ChildWindow is being stored in _newLocation and the class containing _newLocation isn't disposed of:

[ImportingConstructor]
public HomeViewModel(IChildWindowService cwService, INewLocationChildWindow newLocationChildWindow)
        {
            if (!IsDesignTime)
            {
                _cwService   = cwService;
                _newLocation = newLocationChildWindow;
                _catalog     = new AggregateCatalog();
                _catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
                _container   = new CompositionContainer(_catalog);
            }
        }

Is there something else going on here?


Solution

  • Set the creation policy of the ChildWindow to NonShared. Then replace _container.GetExportedValue<INewChildWindow>() with _container.GetExport<INewChildWindow>(). This will give you a Lazy<INewChildWindow>, and you can use the Value property to get the child window. Then to release the export call _container.ReleaseExport, passing in the Lazy that was returned by the call to GetExport.