WPF直接用Window.Close直接关闭窗口导致不能完全退出的问题

时间:2022-11-10 19:15:11

更新:2018 2. 27

这是我两年前写的文章,当时没考虑到debug环境下的问题,事实上debug环境下才会有AdornerLayer,这个问题应该不是单纯由AdornerLayer引起的

刚好今年一月份的时候有个人艾特了我http://bbs.csdn.net/topics/392301858,而我已经很久没写WPF了

请参考提问者最后一个回答:

但网络上也没有别的猜测和处理办法了,只有在窗体里面建立线程句柄 之后 再启动线程。然后 overrides onclosing里面  关掉没退出的线程就可以了。程序可以正常退出。


前几天我在CSDN扔了一个问题,基本描述一下:写了一段这样的代码,来实现获取Control的template,却发现一个这样的问题,就是当我打开了一个window以后,手动调用Close(),窗口的确是消失了,但是当我关闭了主窗口以后,却发现程序没有退出。

 private void ControlTypeSelectingBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
Type type = ControlTypeSelectingBox.SelectedItem as Type; if (type == null)
throw new ArgumentNullException("Type is null"); ConstructorInfo info = type.GetConstructor(System.Type.EmptyTypes);
Control control = info.Invoke(null) as Control; Window window = control as Window;
Window windowAdnore = null; //注意,下面必须要有打开窗口或者把控件放入grid的操作,这样才能让下面的template正确显示出来
if (window != null)
{
window.WindowState = System.Windows.WindowState.Minimized;
window.ShowInTaskbar = false;
window.Owner = this;
window.Show(); windowAdnore = Application.Current.Windows[Application.Current.Windows.Count - ];
}
else
{
control.Visibility = Visibility.Collapsed;
grid.Children.Add(control);
} ControlTemplate template = control.Template; XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true; StringBuilder strbuilder = new StringBuilder();
XmlWriter writer = XmlWriter.Create(strbuilder, settings);
XamlWriter.Save(template, writer); txtTemplateBrowser.Text = strbuilder.ToString(); if (window == null)
grid.Children.Remove(control);
else
{
window.Close();
windowAdnore?.Close();
}
}
catch (Exception ex)
{
txtTemplateBrowser.Text = "<< Error generating template:" + ex.Message + ">>";
}
}

  但是如果我不手动调用Close(),而是让window调用Show以后我点窗口上的关闭键,那就可以彻底退出了(手动点击×以后再关闭主窗口程序可以彻底退出了),然后我再在主窗口重写OnClosed方法

 protected override void OnClosed(EventArgs e)
{
var collections = Application.Current.Windows; foreach (Window window in collections)
{
if (window != this)
window.Close();
} base.OnClosed(e);
}

  这样居然能正常退出了!

  反正问了好多天没人回答,自己再试了几次,发现原来是这样的:

  WPF直接用Window.Close直接关闭窗口导致不能完全退出的问题

  这是打开窗口并且Show以后Application.Current.Windows集合里面的东西,这下你明白了吧,第一项就是主窗口,第三项就是我们新创建的窗口,那么第二项和第四项是什么东西?

  网上怎么查都查不出这是什么(果然WPF用的人还是比较少呀),去翻了一下MSDN的文档:

  WPF直接用Window.Close直接关闭窗口导致不能完全退出的问题

  想了一下,应该是WPF每次打开窗口的时候,首先打开窗口的实例,如果要Show的时候,那么就加载Window的模板(这也就是为什么Window一定要Show才能看见它的控件模板的原因),并且创建一个不可见的AdornerLayer,当我们手动去关闭Window的时候(按那个关闭按钮),是会关闭掉AdornerLayer的,但是直接Close不会。

  不过这个神奇的坑真的没有人发现过吗?(好奇)

  贴正确关闭的代码:

         private void ControlTypeSelectingBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
Type type = ControlTypeSelectingBox.SelectedItem as Type; if (type == null)
throw new ArgumentNullException("Type is null"); ConstructorInfo info = type.GetConstructor(System.Type.EmptyTypes);
Control control = info.Invoke(null) as Control; Window window = control as Window;
Window windowAdnore = null; //注意,下面必须要有打开窗口或者把控件放入grid的操作,这样才能让下面的template正确显示出来
if (window != null)
{
window.WindowState = System.Windows.WindowState.Minimized;
window.ShowInTaskbar = false;
window.Owner = this;
window.Show(); windowAdnore = Application.Current.Windows[Application.Current.Windows.Count - ];
}
else
{
control.Visibility = Visibility.Collapsed;
grid.Children.Add(control);
} ControlTemplate template = control.Template; XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true; StringBuilder strbuilder = new StringBuilder();
XmlWriter writer = XmlWriter.Create(strbuilder, settings);
XamlWriter.Save(template, writer); txtTemplateBrowser.Text = strbuilder.ToString(); if (window == null)
grid.Children.Remove(control);
else
{
window.Close();
windowAdnore?.Close();
}
}
catch (Exception ex)
{
txtTemplateBrowser.Text = "<< Error generating template:" + ex.Message + ">>";
}
}

WPF直接用Window.Close直接关闭窗口导致不能完全退出的问题的更多相关文章

  1. 打开新窗口(window&period;open)关闭窗口(window&period;close)

    打开新窗口(window.open) open() 方法可以查找一个已经存在或者新建的浏览器窗口. 语法: window.open([URL], [窗口名称], [参数字符串]) 参数说明: URL: ...

  2. WPF学习笔记-如何按ESC关闭窗口

    如何按ESC关闭窗口? 在InitializeComponent();下面增加KeyDown事件,如: public ModifyPrice() { InitializeComponent(); th ...

  3. 关于 IE firefox Chrome下的通过用js 关闭窗口的一些问题

    首先IE是可以通过window.close()来关闭浏览器窗口的,但是在firefox和Chrome下是无效的,原因在于: ~~~ie可直接<button onclick="windo ...

  4. WPF MVVM从入门到精通7:关闭窗口和打开新窗口

    原文:WPF MVVM从入门到精通7:关闭窗口和打开新窗口 WPF MVVM从入门到精通1:MVVM模式简介 WPF MVVM从入门到精通2:实现一个登录窗口 WPF MVVM从入门到精通3:数据绑定 ...

  5. 让window&period;close不提示:您查看的网页正在试图关闭窗口。是否关闭此窗口?

    正常来说,当我们调用window.close来关闭从地址栏中打开的窗口时,IE会弹出提示说:您查看的网页正在试图关闭窗口,是否关闭此窗口? 你可以将window.close替换成下边的脚本,然后再测试 ...

  6. 查看程序是否启动或者关闭--比如查看Tomcat是否开启!直接用ps命令查看进程就行了啊

    1.查看程序是否启动或者关闭--比如查看Tomcat是否开启!直接用ps命令查看进程就行了啊 2.Tomcat服务器和虚拟机的关系,Tomcat启动运行过程要调用系统环境变量的java_home啊,J ...

  7. 关闭窗口(window&period;close)

    close()关闭窗口 用法: window.close(); //关闭本窗口 或 <窗口对象>.close(); //关闭指定的窗口 例如:关闭新建的窗口. <script typ ...

  8. JavaScript-打开新窗口(window&period;open)和 关闭窗口(window&period;close)

    JavaScript-打开新窗口 open() 方法可以查找一个已经存在或者新建的浏览器窗口. 语法: window.open([URL], [窗口名称], [参数字符串]) 参数说明: URL:可选 ...

  9. 【WPF】在新线程上打开窗口

    当WPF应用程序运行时,默认会创建一个UI主线程(因为至少需要一个),并在该UI线程上启动消息循环.直到消息循环结束,应用程序就随即退出.那么,问题就来了,能不能创建新线程,然后在新线程上打开一个新窗 ...

随机推荐

  1. oracle 查询结果集运算

    intersec:交集minus:差集union:进行表连接后会筛选掉重复的记录,表连接之后对结果进行排序运算,删除重复记录在返回结果. union all:只是简单的将两个结果合并就返回.无论是否有 ...

  2. vsftp的设置选项

    设置匿名用户上传的文件的权限: anon_umask=  匿名用户新增文件的umask 数值.默认值为077.     VSFTPD的设置选项 VSFTPD的配置文件/etc/vsftpd/vsftp ...

  3. C&plus;&plus;格式化字符函数

    格式化有很多种方法,啊,1,sprintf函数可以实现格式化字符串,并保存到一个字符数组2,snprintf也能实现但比起sprintf函数稍微要安全一些了啊3,ostringstream对象也能实现 ...

  4. oracle 归档日志满 报错ORA-00257&colon; archiver error&period; Connect internal only&comma; until freed

    归档日志满导致无法用户无法登陆 具体处理办法 --用户登陆 Microsoft Windows [Version 6.1.7601] Copyright (c) Microsoft Corporati ...

  5. PHP ORM笔记

    1.ORM是什么? 经常听到程序员的面试中会问到对ORM的了解,但是一直不知道ORM是个什么鬼东西,知道有一天在百度上顺带看到才发现ORM就是我们平时在框架中一直使用的数据库对象操作.ORM(Obje ...

  6. ZZCMS8&period;1&vert;代码审计

    这周的审计任务 ZZCMS8.1是站长招商网内容管理系统.审计这个CMS的原因很多,这里就不详说了(其实是漏洞类型多点)                                         ...

  7. Asp&period;Net Core 程序部署到Linux(centos)生产环境(二):docker部署

    运行环境 照例,先亮环境:软件的话我这里假设你已经批准好了.net core 运行环境,未配置可以看我的这篇[linux(centos)搭建.net core 运行环境] 腾讯云 centos:7.2 ...

  8. flask 电子邮件进阶实践-用模板发送163邮件

    电子邮件进阶实践 下面来学习构建邮件的HTML正文,并使用模板组织内容. 一封电子邮件的正文可以是纯文本(text/plain),也可以是HTML格式的文本(text/html).处于全面的考虑,一封 ...

  9. 28&period; pt-table-sync

    前提:得有checksum表 pt-table-sync --replicate=pt.checksum \h=192.168.100.101,P=3306,u=admin,p=admin \h=19 ...

  10. &lbrack;转&rsqb;vue数据绑定&lpar;数据&comma;样式&comma;事件&rpar;

    1.mounted 与 methods 与 computed 与 watched区别 From:https://blog.csdn.net/qinlulucsdn/article/details/80 ...