我一直想知道这一点,我找到了最好的解决方案。要重现此问题,只需:
添加以下代码:
public MainWindow()
{
InitializeComponent();
//add code
Window1 w1 = new Window1();
//following is in my actual project
DataContext = new AllUserQueryiesViewModel(new CommonQueryTestSubWindow());
}
运行并关闭MainWindow。
当时,我希望应用程序关闭,但我的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中存储一个窗口,这导致了主要问题。我知道你必须有更好的解决方案,请帮忙。
答案 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()方法。或者使它成为一个拥有的窗口,以便它与主窗口同时消失。或者显示它以便用户可以控制应用程序中的窗口。随便挑选。