【WPF】如何让弹出的窗口"阻塞"
2009-09-02 20:43
197 查看
还存在一些问题,再研究一下
1、ComponentDispatcher其实可以不用
2、new一个DispatcherFrame其实是把一个消息循环(姑且称作嵌套消息循环)当做一个DispatchFrame来处理,在这个消息循环结束之前,原来的代码就是阻塞的
3、正是因为第二个原因,如果再次弹出一个窗口,将是在前一个嵌套消息循环中,再次执行2,也就会导致第一个窗口关闭,并不会立即执行后面的代码。
【场景描述】
某些时候可能会有这种需求,一个用户界面里面分为好多个功能区域。这些功能区域有时候会有一些“模态”的弹出窗口的交互,这些弹出窗口需要:
1、只影响当前区域。即鼠标或者键盘无法操作当前区域,而其他区域不受影响。比如说,有好多个选项卡页面,每个选项卡页面弹出的窗口只影响当前选项卡,而不影响其他的选项卡。
2、窗口未关闭之前,后面的代码不执行,即“阻塞”。
【问题分析】
WPF中的窗口的弹出提供了两个方法:Show和ShowDialog。其中,Show方式是一个非“阻塞”的方法,即:调用完Show之后立即返回,后面的代码将立即被执行,但是这个方法不会挡住整个窗口。而ShowDialog方法是一个“阻塞”的方法,即调用完ShowDialog之后需要等窗口关闭代码才会继续执行。然而,ShowDialog会挡住整个窗口,而不是指定的区域。
综合这个两个方法考虑,其实,对于场景中的第一条,我们可以考虑通过调用Show让窗口弹出之后,即将该区域置为IsEnabled=false来模拟“模态”的窗口,这个倒不是很难。问题在于第二条,如何让窗口“阻塞”住当前代码的继续执行呢?即:
var win = new MyDialog();
win.Show();
// 关闭后才要执行的代码
1、用一个while死循环,直到关闭才跳出。如果采用这种方式,那我们不得不好好考虑一下,在UI线程做死循环UI还有没有办法响应。当然,方法是有的,可以实现一个WPF版的DoEvents方法,然后在循环中调用。DoEvents相关的代码可以参见:http://www.cnblogs.com/sheva/archive/2006/08/24/485790.html
2、用异步模式来写。代码将类似于:
var win = new MyDialog();
// MyCloseCallback是一个窗口关闭时调用的回调
win.Show(MyCloseCallback);
这样确实可以满足需求,不过我们不得不忍受把一份代码拆开为两份来写的痛苦。当然,匿名方法和Lamba可以带来一些缓解,但是写起来始终不是那么舒服。
难道,我们除了使用可怕的while死循环+DoEvents,或者忍受别扭的代码之外,就没有别的办法了么?
【揭开ShowDialog的面纱】
其实,回过头再去想,为什么ShowDialog方法就可以阻塞代码的执行呢?如果我们能够知道如何阻塞代码,然后把“挡住”整个窗口的部分给去掉,不就OK了么?
好,我们请出神器Reflector打开Window的ShowDialog方法一窥究竟。
var btn = sender as Button;
var dialog = new MyDialog
{
Width = 300,
Height = 200,
Content = btn.Tag,
WindowStartupLocation = WindowStartupLocation.CenterOwner
};
var border = this.FindName((string)btn.Tag) as Border;
dialog.Open(border);
// 在窗口关闭之前不会执行
MessageBox.Show(string.Format("{0}上弹出对话框结束!", btn.Tag));
代码下载
/Files/RMay/TryMessageBox.zip
1、ComponentDispatcher其实可以不用
2、new一个DispatcherFrame其实是把一个消息循环(姑且称作嵌套消息循环)当做一个DispatchFrame来处理,在这个消息循环结束之前,原来的代码就是阻塞的
3、正是因为第二个原因,如果再次弹出一个窗口,将是在前一个嵌套消息循环中,再次执行2,也就会导致第一个窗口关闭,并不会立即执行后面的代码。
【场景描述】
某些时候可能会有这种需求,一个用户界面里面分为好多个功能区域。这些功能区域有时候会有一些“模态”的弹出窗口的交互,这些弹出窗口需要:
1、只影响当前区域。即鼠标或者键盘无法操作当前区域,而其他区域不受影响。比如说,有好多个选项卡页面,每个选项卡页面弹出的窗口只影响当前选项卡,而不影响其他的选项卡。
2、窗口未关闭之前,后面的代码不执行,即“阻塞”。
【问题分析】
WPF中的窗口的弹出提供了两个方法:Show和ShowDialog。其中,Show方式是一个非“阻塞”的方法,即:调用完Show之后立即返回,后面的代码将立即被执行,但是这个方法不会挡住整个窗口。而ShowDialog方法是一个“阻塞”的方法,即调用完ShowDialog之后需要等窗口关闭代码才会继续执行。然而,ShowDialog会挡住整个窗口,而不是指定的区域。
综合这个两个方法考虑,其实,对于场景中的第一条,我们可以考虑通过调用Show让窗口弹出之后,即将该区域置为IsEnabled=false来模拟“模态”的窗口,这个倒不是很难。问题在于第二条,如何让窗口“阻塞”住当前代码的继续执行呢?即:
var win = new MyDialog();
win.Show();
// 关闭后才要执行的代码
1、用一个while死循环,直到关闭才跳出。如果采用这种方式,那我们不得不好好考虑一下,在UI线程做死循环UI还有没有办法响应。当然,方法是有的,可以实现一个WPF版的DoEvents方法,然后在循环中调用。DoEvents相关的代码可以参见:http://www.cnblogs.com/sheva/archive/2006/08/24/485790.html
2、用异步模式来写。代码将类似于:
var win = new MyDialog();
// MyCloseCallback是一个窗口关闭时调用的回调
win.Show(MyCloseCallback);
这样确实可以满足需求,不过我们不得不忍受把一份代码拆开为两份来写的痛苦。当然,匿名方法和Lamba可以带来一些缓解,但是写起来始终不是那么舒服。
难道,我们除了使用可怕的while死循环+DoEvents,或者忍受别扭的代码之外,就没有别的办法了么?
【揭开ShowDialog的面纱】
其实,回过头再去想,为什么ShowDialog方法就可以阻塞代码的执行呢?如果我们能够知道如何阻塞代码,然后把“挡住”整个窗口的部分给去掉,不就OK了么?
好,我们请出神器Reflector打开Window的ShowDialog方法一窥究竟。
var btn = sender as Button;
var dialog = new MyDialog
{
Width = 300,
Height = 200,
Content = btn.Tag,
WindowStartupLocation = WindowStartupLocation.CenterOwner
};
var border = this.FindName((string)btn.Tag) as Border;
dialog.Open(border);
// 在窗口关闭之前不会执行
MessageBox.Show(string.Format("{0}上弹出对话框结束!", btn.Tag));
代码下载
/Files/RMay/TryMessageBox.zip
相关文章推荐
- 【WPF】如何让弹出的窗口"阻塞"
- WPF中,如何屏蔽WebBrowser弹出的脚本错误窗口?
- WPF如何弹出窗口
- [WPF]如何实现设置UserControl 弹出窗口的Owner属性功能
- [WPF]如何实现设置UserControl 弹出窗口的Owner属性功能
- 如何用弹出窗口显示进度 - 回复 "嘿嘿嘿" 的问题
- [WPF]如何实现设置弹出窗口的Owner属性功能?
- Silverlight中多个Xaml("场景"? or "窗口"? )之间的切换/调用/弹出/传参数问题小结
- 如何解决在ASP.NET中应用JavaScript的 alert 函数时弹出的窗口背景全部为白色的问题
- ]如何点击按钮弹出新窗口,输入数据后返回并刷新页面?(C#代码)
- js如何弹出新窗口
- Selenium-webdriver系列教程(六)————如何捕获弹出窗口
- AD认证模式下如何通过表单登录来代替WINDOWS弹出窗口的方法
- popupwindow 如何实现弹出菜单效果_popupwindow 实现弹出窗口范例
- 如何弹出一个模式窗口来显示进度条
- 如何定制弹出窗口的大小及其位置
- WPF—QQ界面(四):单击QQ昵称弹出个人简介窗口的效果实现
- 如何定制弹出窗口的大小及其位置
- 如何点击按钮弹出新窗口,输入数据后返回并刷新页面?
- rails如何做调查弹出窗口