Cannot set Visibility or call Show or ShowDialog after window has closed.

Aug 12, 2009 at 10:22 AM

Im using unity along side the composite application block and am recieving this exception.

Cannot set Visibility or call Show or ShowDialog after window has closed.

The situation is that I am launching the window in question off of a context menu in my shell window. If I then close the window using normal red cross at the top right of the windiw and use the context menu on the shell to again to open the window I receieve the error. The code that opens the window inside the handler of the context menu is below

var processAnalyserPresenter = Container.Resolve<IProcessAnalyserPresenter>();

processAnalyserPresenter.View.Show();

If I dont use unity to resolve my presenter class and just new up the concrete the problem goes away. The registration of both the presenter and the view is below.

Container.RegisterType<Views.ProcessAnalyser.IProcessAnalyserPresenter, Views.ProcessAnalyser.ProcessAnalyserPresenter>();
Container.RegisterType<Views.ProcessAnalyser.IProcessAnalyserView, Views.ProcessAnalyser.ProcessAnalyserView>();
So neither is regsitered as a singleton but I seem to be getting back the same instance of the view which is causing my problem.

Aug 14, 2009 at 2:28 PM

Can you provide a demo app (bare-bones) that emulates the problem?  I for one would be interested in why you are getting the behavior - I recall a similiar issue with the Smart Client Software Factory (back in the day) and it was caused by a dangling reference that wasn't releasing the view; successive calls resulted in an empty view (all components were disposed).

Aug 17, 2009 at 11:36 AM

Hi Bill,

I'm having problems achieving the following. I have a module (ModuleA) which injects a view into the shell. A button on this view fires a command which when handled I want to open a new window. Before the window shows I want to inject a view from another module into it. I need to be able to close the new window and refire the command from ModuleA to instantiate a new instance of the window and Show it again. The problem Im having is properly registering the view that goes into the new window. Depending on how I register it it either only shows the first time or shows mutilple times.

Below is a link to my bare-bones project - any help would be greatly appreciated.

http://dl.getdropbox.com/u/416443/CALDemo2.zip

Thanks,

Dav

 

Aug 17, 2009 at 4:26 PM
Edited Aug 17, 2009 at 4:32 PM

Hi dav_evans,

This is more a PRISM issue than a Unity Issue.   Oddly the RegionViewRegistry class doesn't provide a means to remove views once it is used to add them (thus "shows multiple times") so going that route seemed to be a dead-end.   The RegionManager itself has a lot going on under the hood - seems a delicate balance is being thrown off somewhere...   So I tried a different approach - I create a new region manager within the scope of ViewModel_RunWorkflow and use it.   Seems to be happy with this :)

public class TestPresenter
{
    public ITestView View { get; set; }
    public TestViewModel ViewModel { get; set; }
    public IRegionManager regManager { get; set; }
    public IUnityContainer Container { get; set; }

    public TestPresenter(ITestView view, TestViewModel viewModel, IRegionManager regionManager, IUnityContainer container)
    {
        View = view;
        ViewModel = viewModel;
        regManager = regionManager;
        Container = container;
        ViewModel.RunWorkflow += new EventHandler(ViewModel_RunWorkflow);
        View.DataContext = ViewModel;
    }

    void ViewModel_RunWorkflow(object sender, EventArgs e)
    {
        IRegionManager manager = null;

        //open a new WorkflowRunner window
        var runner = new WorkflowRunner();

        manager = regManager.CreateRegionManager();
        RegionManager.SetRegionManager(runner, manager);    

        //get new instance of workflow view
        var workflowView = Container.Resolve<IMyWorkflowView>();
        var workflowViewModel = Container.Resolve<IMyWorkflowViewModel>();
        workflowViewModel.TheGuid = Guid.NewGuid();
        workflowView.DataContext = workflowViewModel;

        manager.Regions[RegionNames.WorkflowRunnerMainRegion].Add(workflowView);

        runner.Closing += (source, args) =>
        {
            manager.Regions[RegionNames.WorkflowRunnerMainRegion].Remove(workflowView);
        };
        runner.Show();
    }
}

 

Aug 17, 2009 at 5:18 PM

Hi Bill,

Thanks for your swift reply. Looks like the static methods off of the RegionManager are the way to go.

 

Cheers,

Dav