WPF应用程序类和主窗口初始化
public static int WindowCounter = 0;
[STAThread]
public static void Main()
{
ShowBeforeApplicationCreation();
//ShowAfterApplicationCreation();
}
public static void ShowBeforeApplicationCreation()
{
ShowWindow();
ShowWindow();
ShowWindow();
var app = new Application();
app.Run();
}
public static void ShowAfterApplicationCreation()
{
var app = new Application();
ShowWindow();
ShowWindow();
ShowWindow();
app.Run();
}
public static void ShowWindow()
{
var window = new Window { Title = string.format("Title{0}", WindowCounter++) };
window.Show();
}
如果我运行的代码所示,我关闭任何它会关闭所有窗口的窗口。如果我切换到注释掉的部分,关于哪个窗口会导致所有窗口关闭(大部分时间是最后一个窗口)似乎是随机的。
如何应用决定哪个窗口将导致关闭该程序?
是该窗口中的“主”窗口?
让我们来定义关闭过程中OwningWindow(希望这个名字是不是在这方面载)窗口。我怎样才能确保显示的第一个窗口是OwningWindow?
最后一个问题是我的主要问题。我不想打开其他二级窗口,让用户关闭主窗口,并让进程继续运行。或者,我是否必须让窗口的后续窗口成为OwningWindow的窗口?
如何应用决定哪个窗口将导致关闭该程序?
默认情况下,Application
类将退出Run()
方法(因此这里的全过程)时,所有打开的窗口已经关闭。根据你的代码示例,似乎有一个皱纹:Application
类不考虑它自己创建之前打开的任何窗口。如果你不告诉它任何窗口(即通过传递参考Run()
方法),那么任何窗口关闭都会导致Run()
方法退出,因为Application
类确实是看到窗口的关闭,但认为在这个过程中没有窗户。
是该窗口中的 “主” 窗口?
默认情况下,“主”窗口是要在AppDomain
中实例化的第一个窗口。您可以随时通过设置Application
对象的MainWindow
属性来覆盖此属性。
当然,如上面所讨论的,Application
对象没有办法看到被创建之前它本身创建的窗口。一个例外:如果您将窗口传递给Run()
方法,即使该窗口是在Application
对象之前创建的,也可以成为MainWindow
。如果所有的窗口都是在Application
之前创建的,并且您没有将这些窗口的引用传递给Run()
方法,那么根本没有主窗口。
如果要确定性地指定单个窗口以在窗口关闭时导致进程退出,则有一个选项是将其传递给Application.Run()
方法。例如:
class Program
{
public static int WindowCounter = 0;
private static Window _firstWindow;
[STAThread]
public static void Main()
{
ShowBeforeApplicationCreation();
}
public static void ShowBeforeApplicationCreation()
{
ShowWindow();
ShowWindow();
ShowWindow();
var app = new Application();
app.Run(_firstWindow);
}
public static void ShowWindow()
{
var window = new Window { Title = string.Format("Title{0}", WindowCounter++) };
window.Show();
_firstWindow = _firstWindow ?? window;
}
}
也就是说,默认Application.ShutdownMode
值为ShutdownMode.OnLastWindowClose
,所以没有做别的事情,程序应该不关闭,直到最后一个窗口被关闭。这只是因为类似乎没有注意到在实例化之前发生的窗口打开(它显然会对窗口的实际创建做出反应,而不是在启动时搜索打开的窗口的过程)。
很明显,在Application.Run()
之前创建窗口被称为混淆方法;它似乎认为如果任何一个窗户关闭,窗户仍然没有开放。如果你传递给其中一个窗口的引用,它将不会返回到该窗口关闭之前,该窗口是它“知道”的唯一窗口;任何其他窗口的关闭都会被忽略,因为它知道的一个窗口仍然是打开的。 (在我的测试中,程序不会退出,直到所有的窗口关闭,它们都在Application
对象之后创建,这与Application
类正确注释的上述想法一致任何窗口创建和/或显示后它自己创建)。
恕我直言,最好的办法是不要混淆的方法。它无法正确处理在Application
对象创建之前显示的窗口。所以,不要这样做。确保在创建Application
之后,才会创建全部。如果您关闭的具体行为与默认的ShutdownMode.OnLastWindowClose
行为不同,那么这应该很简单,可以实现。
这可能是因为刚刚ShutdownMode
属性设置为别的东西一样简单。例如,ShutdownMode.OnMainWindowClose
。在这种情况下,您当然需要确保某个窗口是主窗口,否则该进程将不会退出。您可以明确,甚至通过传递窗口参考Run()
方法在创建了使用默认行为做到这一点(即创建主窗口的第一个窗口,但Application
对象被创建之后),通过设置MainWindow
财产Application
对象之前的所有窗口。
让我们来定义关闭过程中OwningWindow(希望这个名字是不是在这方面载)窗口。我怎样才能确保显示的第一个窗口是OwningWindow?
从上面的讨论中,你也许可以自己回答这个问题。 :)
首先, “拥有窗口” 实际上是MainWindow
。但是,默认情况下,Application.Run()
方法仅在所有窗口(它已知)已关闭时才会返回。只有通过隐藏Application
方法中的一些窗口,才能看到某个“拥有窗口”负责关闭程序(在默认的ShutdownMode
方案中)。实际上,如果你想要的只是在某些特定的窗口本身关闭时关闭程序,那么正确的方法是确保MainWindow
设置正确,并且已将Application.ShutdownMode
设置为值为ShutdownMode.OnMainWindowClose
。这样一来,你正在使用WPF完全明确一下你想要的确切行为,它不会有机会搞砸了,即使你做一些怪异像创建Application
对象之前创建一个Window
对象。:)
Ah默认ShutdownMode解释了为什么当我通过窗口它仍然有相同的行为(当我期望我通过的窗口关闭应用程序退出时)。感谢您的详细回复! – user815512
继续这个主题,让我们说,作为我的应用程序启动的一部分,我想显示一个窗口,然后在关闭之后显示另一个窗口。我可以通过不同的窗口调用app.Run()两次来做到这一点吗?或者是一些涉及Application类的状态,将禁止这个? – user815512
@ user815512:我不知道我的头顶。我希望你能够多次调用'Run()'。但是我也认为如果这是你的场景,你最好将'ShutdownMode'设置为'OnExplicitShutdown',这样你的代码就可以完全控制。或者,使用'OnMainWindowClose',只要您在关闭第一个窗口并设置MainWindow属性之前创建第二个窗口,则关闭第一个窗口不应导致应用程序退出。基本上:为什么要问麻烦? WPF允许你完全控制关闭逻辑,所以你也可以。 –