WindowRegionAdapter Close Window

Dec 30, 2008 at 12:45 PM
I want to be able to close the windows created by the WindowRegionAdapter via a button on the UserControl.  I've tried the following with limited success.  If I open a window via the WindowRegionAdapter and then close it via regionManager.Regions["MainRegion"].Remove(view); it closes fine the first time but the next time I open the window and close it I get the following error.

The region does not contain the specified view.

Code changes to sample project WindowsRegionAdapter
  1. Add a button to View1
            <Button Name="btnClose" Command="{Binding}"  Width="75" Height="30" VerticalAlignment="Bottom" Margin="0,0,0,5">Close</Button>
  2. Change the View1() Contructor to the following
            public View1()
            {
                InitializeComponent();
                btnClose.CommandParameter = this;
            }
  3. Change the MyModuleInit.cs button_Click to the following (adding the method CloseWindow):
            void button_Click(object sender, System.Windows.RoutedEventArgs e)
            {
                View1 view = new View1();
                view.Title = "Some Title";
                view.btnClose.DataContext = new DelegateCommand<View1>(CloseWindow);
                _regionManager.Regions["MyWindowRegion"].Add(view);
            }

            void CloseWindow(View1 view)
            {
                _regionManager.Regions["MyWindowRegion"].Remove(view);
            }
  4. Run the app and open/close windows via the buttons.
Perhaps I'm going about this all the wrong way but I don't want to force the user to click on the X in the title bar to close windows.  There has to be a better way.
Dec 30, 2008 at 1:39 PM
Some additional info.  I added the WindowRegionAdapter.cs file to my project to I could debug where the error was coming from and here is what I found.

            private void window_Deactivated(object sender, EventArgs e)
            {
                IRegion region = _regionWeakReference.Target as IRegion;
                Window window = sender as Window;

                if (window != null)
                    region.Deactivate(window.Content);
            }

The error is being thrown at the region.Deactivate(window.Content); line.

Dec 30, 2008 at 1:44 PM
I'm not sure if this is the correct fix but at least it works for me.  I changed the above method to the following:

            private void window_Deactivated(object sender, EventArgs e)
            {
                IRegion region = _regionWeakReference.Target as IRegion;
                Window window = sender as Window;

                if (window != null)
                    if (region.Views.Contains(window.Content))
                        region.Deactivate(window.Content);
            }
Jan 20, 2009 at 7:32 AM
Hi bsleys,

the reason why the exception is thrown when closing the window is that it gets deactivated after it has been closed since there is still the window_Deactivated event handler registered for it.

So the proper fix would be to de-register the event-handlers when the view is removed:

private void Views_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
...
else if (e.Action == NotifyCollectionChangedAction.Remove)
                {
                    foreach (object view in e.OldItems)
                    {
                        Window window = GetContainerWindow(view);
                        if (window != null)
                        {
                            window.Activated -= window_Activated;
                            window.Deactivated -= window_Deactivated;
                            window.Closed -= window_Closed;
                            window.Close();
                        }

                        // dispose view
                        var disposable = view as IDisposable;
                        if (disposable != null)
                            disposable.Dispose();

                        _containerWindows.Remove(view);
                    }
                }

hope this helps!



Jan 20, 2009 at 1:33 PM
Thanks that does help.

However am I missing something?  I don't have a _containerWindows object to remove the view from. (ref. the last line of code you posted)