为什么在MainWindow关闭后不会自动处理和收集WPF窗口?

时间:2014-01-15 09:24:11

标签: c# wpf visual-studio garbage-collection

我一直想知道这一点,我找到了最好的解决方案。要重现此问题,只需:

  1. 在新的WPF应用程序中添加新窗口。
  2. 添加以下代码:

    public MainWindow()
    {
        InitializeComponent();
        //add code
        Window1 w1 = new Window1();
        //following is in my actual project
        DataContext = new AllUserQueryiesViewModel(new CommonQueryTestSubWindow());
    }
    
  3. 运行并关闭MainWindow。

  4. 当时,我希望应用程序关闭,但我的VS2010似乎仍在运行。那么为什么以及如何解决呢?

    --------- UPDATE -----------------

    我想我最好在我的真实项目中表达自己的风景,让你更好地理解我的原因 这个。考虑查询列表和打开查询功能,就像TFS工作项查询一样。 我正在创建一些usercontrol来执行此操作,我们团队中的其他人可以在同一个应用程序中使用。 查询列表和打开的查询属于单独的用户控件,因此用户(其他程序员)可以将打开的查询放在他们想要的任何位置(ContentControl)。 ViewModels:

    public class AllVM
    
        {
            public AllVM(IOneVMContainer container)
            {
                OneVMs = new ObservableCollection<OneVM>()
               {
                   new OneVM(container),
                   new OneVM(container)
               };
            }
    
            public ObservableCollection<OneVM> OneVMs { get; set; }
            public OneVM SelectedOneVM { get; set; }
    
            public void OpenOne()
            {
                SelectedOneVM.Open();
            }
        }
    
    public class OneVM
    {
        IOneVMContainer container;
        public OneVM(IOneVMContainer container)
        {
            this.container = container.NewInstance();
        }
        //I want to open and close the view from viewmodel
        public void Open()
        {
            container.GetContentCtl().Content = this;
            container.Show();
        }
        public void Close()
        {
            container.Close();
        }
    }
    

    要在ViewModel中打开和关闭视图,我创建了这样的界面

    //Is it good to use interface?
    //Maybe a better interface?
    public interface IOneVMContainer
    {
        IOneVMContainer NewInstance();
        void Show();
        void Close();
        ContentControl GetContentCtl();
    }
    

    使用上面的ViewModels:

    //my usercontrol to hold AllVM
    public AllUC()
    {
        InitializeComponent();
        DataContext = new AllVM(new  OneContainerWindow());
    }
    
    //implement by other team members
    public partial class OneContainerWindow : Window,IOneVMContainer
    {
        public OneContainerWindow()
        {
            InitializeComponent();
        }
        public IOneVMContainer NewInstance()
        {
           return new OneContainerWindow();
        }
        public ContentControl GetContentCtl()
        {
            return contentCtl1;
        }
    }
    

    所以我想知道是否不可避免地在ViewModel中存储一个窗口,这导致了主要问题。我知道你必须有更好的解决方案,请帮忙。

2 个答案:

答案 0 :(得分:4)

首先,不要在构造函数中实例化一个新窗口。

现在,对于您的问题,您需要设置窗口的Owner

public MainWindow()
{
    InitializeComponent();
    Loaded += MainWindow_Loaded;
}

void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    Window w = new Window() { Owner = this };
}

这样就可以正确处理子窗口。

答案 1 :(得分:3)

只要您的应用程序仍具有实时Window实例,WPF调度程序循环就会一直运行。你的Window1对象。事实上它是不可见的,因为你从来没有调用它的Show()方法,并且你永远不能自己关闭窗口,因为你丢失了对窗口的引用并没有改变那个结果。

很不清楚为什么要考虑这样做,但一个解决方法是强制调度程序循环在主窗口关闭时退出:

    protected override void OnClosed(EventArgs e) {
        base.OnClosed(e);
        Application.Current.Dispatcher.InvokeShutdown();
    }

还有很多其他的东西,比如让“w1”成为你班级的一个领域,所以你可以调用它的Close()方法。或者使它成为一个拥有的窗口,以便它与主窗口同时消失。或者显示它以便用户可以控制应用程序中的窗口。随便挑选。