zoukankan      html  css  js  c++  java
  • WPF直接用Window.Close直接关闭窗口导致不能完全退出的问题

    更新:2018 2. 27

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

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

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

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


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

     1 private void ControlTypeSelectingBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
     2         {
     3             try
     4             {
     5                 Type type = ControlTypeSelectingBox.SelectedItem as Type;
     6 
     7                 if (type == null)
     8                     throw new ArgumentNullException("Type is null");
     9 
    10                 ConstructorInfo info = type.GetConstructor(System.Type.EmptyTypes);
    11                 Control control = info.Invoke(null) as Control;
    12 
    13                 Window window = control as Window;
    14                 Window windowAdnore = null;
    15 
    16                 //注意,下面必须要有打开窗口或者把控件放入grid的操作,这样才能让下面的template正确显示出来
    17                 if (window != null)
    18                 {
    19                     window.WindowState = System.Windows.WindowState.Minimized;
    20                     window.ShowInTaskbar = false;
    21                     window.Owner = this;
    22                     window.Show();
    23 
    24                     windowAdnore = Application.Current.Windows[Application.Current.Windows.Count - 1];
    25                 }
    26                 else
    27                 {
    28                     control.Visibility = Visibility.Collapsed;
    29                     grid.Children.Add(control);
    30                 }
    31                  
    32                 ControlTemplate template = control.Template;
    33 
    34                 XmlWriterSettings settings = new XmlWriterSettings();
    35                 settings.Indent = true;
    36 
    37                 StringBuilder strbuilder = new StringBuilder();
    38                 XmlWriter writer = XmlWriter.Create(strbuilder, settings);
    39                 XamlWriter.Save(template, writer);
    40 
    41                 txtTemplateBrowser.Text = strbuilder.ToString();
    42 
    43                 if (window == null)
    44                     grid.Children.Remove(control);
    45                 else
    46                 {
    47                     window.Close();
    48                     windowAdnore?.Close();
    49                 }
    50             }
    51             catch (Exception ex)
    52             {
    53                 txtTemplateBrowser.Text = "<< Error generating template:" + ex.Message + ">>";
    54             }
    55         }

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

     1 protected override void OnClosed(EventArgs e)
     2 {
     3        var collections = Application.Current.Windows;
     4  
     5         foreach (Window window in collections)
     6         {
     7                if (window != this) 
     8                    window.Close();
     9         }
    10  
    11          base.OnClosed(e);
    12 }

      这样居然能正常退出了!

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

      

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

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

      

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

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

      贴正确关闭的代码:

     1         private void ControlTypeSelectingBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
     2         {
     3             try
     4             {
     5                 Type type = ControlTypeSelectingBox.SelectedItem as Type;
     6 
     7                 if (type == null)
     8                     throw new ArgumentNullException("Type is null");
     9 
    10                 ConstructorInfo info = type.GetConstructor(System.Type.EmptyTypes);
    11                 Control control = info.Invoke(null) as Control;
    12 
    13                 Window window = control as Window;
    14                 Window windowAdnore = null;
    15 
    16                 //注意,下面必须要有打开窗口或者把控件放入grid的操作,这样才能让下面的template正确显示出来
    17                 if (window != null)
    18                 {
    19                     window.WindowState = System.Windows.WindowState.Minimized;
    20                     window.ShowInTaskbar = false;
    21                     window.Owner = this;
    22                     window.Show();
    23 
    24                     windowAdnore = Application.Current.Windows[Application.Current.Windows.Count - 1];
    25                 }
    26                 else
    27                 {
    28                     control.Visibility = Visibility.Collapsed;
    29                     grid.Children.Add(control);
    30                 }
    31                  
    32                 ControlTemplate template = control.Template;
    33 
    34                 XmlWriterSettings settings = new XmlWriterSettings();
    35                 settings.Indent = true;
    36 
    37                 StringBuilder strbuilder = new StringBuilder();
    38                 XmlWriter writer = XmlWriter.Create(strbuilder, settings);
    39                 XamlWriter.Save(template, writer);
    40 
    41                 txtTemplateBrowser.Text = strbuilder.ToString();
    42 
    43                 if (window == null)
    44                     grid.Children.Remove(control);
    45                 else
    46                 {
    47                     window.Close();
    48                     windowAdnore?.Close();
    49                 }
    50             }
    51             catch (Exception ex)
    52             {
    53                 txtTemplateBrowser.Text = "<< Error generating template:" + ex.Message + ">>";
    54             }
    55         }
  • 相关阅读:
    恶意代码分析实战-确认EXE什么时候编译的
    恶意代码分析-工具收集
    Bug Bounty Reference
    [ Mongodb ] 问题总汇
    [ kvm ] 四种简单的网络模型
    [ kvm ] 进程的处理器亲和性和vCPU的绑定
    虚拟化概念总结
    centos7安装tengine强制使用HTTPS访问
    [ SSH 两种验证方式原理 ]
    [ Centos 7 iscsi搭建 及 1台客户端同时挂载多台iscsi服务端问题 ]
  • 原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/6130005.html
Copyright © 2011-2022 走看看