WPF:更好得理解对话框和ShowDialog方法 .
1. 关于标准对话框
首先,一个标准的对话框应该严格具备至少如下特点:
- 只要背后父窗体显示,它一定会显示,并且覆盖在父窗体之上。
- 对话框的窗口标题不会显示在任务栏中的,任务栏仅会显示主窗体的名称。
- 对于模式对话框(Model Dialog),只有对话框关闭后,背后父窗体才会获得焦点。无模式对话框(Modeless Dialog)没有这样的限制。
那么,举个例子,比如记事本中的字体选择对话框就是一个模式对话框,它的行为举止完全符合上述特点。
除了上述3点最不可缺少的。其次就是一些细节问题,比如对话框该不该显示图标?
一般情况下多数对话框都是没有图标的,不过额外为对话框添加图标也可以的。
还有就是对话框的大小问题,对话框该不该允许用户调节大小?
我个人认为如果没有什么特殊要求的话,每个对话框都应该允许用户调节大小的。毕竟固定大小的对话框会在大分辨率环境下觉得太小,或者小分辨率环境下用户觉得太大。当然有些对话框在显示前会根据显示器环境参数来自动调节大小,不过如果可能的话,还是允许用户调整大小比较好也比较方便。
好了,通过上面了解了对话框的基本要求和特点,下面就开始讲对于WPF框架,怎样创建一个更好的对话框。
首先我们需要把Window的ShowInTaskbar属性设置成False,这样对话框不会在任务栏中显示。
其次是对话框的颜色问题,标准对话框的背景颜色应该和Windows窗体控件颜色保持一致,在WPF中,窗体的默认颜色是白色的,在Windows 7下多数亮度比较大的Aero主题下可能看得不明显,把主题调节成经典Windows主题,再看对话框背景就很明显了,比如,记事本中的对话框:
WPF中的SystemColors类型提供系统预定义颜色的封装,可以动过一个简单的DynamicResource标记扩展就可以显示成系统控件颜色。其中的ControlColor就是我们想要的颜色。由于WPF中背景颜色类型是Brush同时用DynamicResource绑定一个资源键,所以最后用SystemColors的ControlBrushKey属性。(这里用DynamicResource可以随时根据系统颜色变化而改变当前程序的颜色)。
代码如下:
Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
接着关于对话框的大小,对于固定大小的对话框,设置Window类型的ResizeMode属性为NoResize,对话框的大小就固定了,如下:
对于可以调节大小的对话框,你可以直接使用默认样式,不过这样的话最大化和最小化按钮还在,这种对话框看起来比较不舒服也很少见,所以你可以把WindowStyle设置成ToolWindow就是工具窗口,这样就只有关闭按钮显示了(不过,工具窗口的关闭按钮要略小):
而对于大多数标准可调节大小的Windows对话框,比如打开文件对话框,它的右上角只显示标准的关闭按钮(比工具窗口的关闭按钮要大),同时右下角有一个调节大小指示区域来提示用户虽然我看起来像固定大小的对话框但是我是可以调节大小的:
对于右下角的缩放提示区域,可以设置Window类型的ResizeMode为CanResizeWithGrip。
上述要求,在WPF中可以实现的功能有如下代码:
ShowInTaskbar="False"
ResizeMode="CanResizeWithGrip"
Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
不过不幸的是,当前的WPF不能直接隐藏最小化按钮和最大化按钮,同时也不支持窗体图标的隐藏。解决方案可以参考:WPF:窗体不显示或禁用最大化、最小化、关闭按钮、图标以及对话框显示。
那么当上述功能都实现后,一个最标准的可调节大小的Window对话框就的结果应该是这样的(注意背景不是白色的):
在经典主题下是这样的:
上面都是讲标准Windows对话框。不过,我个人认为,既然对话框应该允许用户更改大小,那么为什么要把最大化按钮去掉呢?有了最大化按钮可以使对话框立即铺满屏幕而不需要用户再用鼠标慢慢放大。当然最小化按钮是不该有的,因为对话框不显示在任务栏里。
所以理想对话框应该是这样的(可能看起来有些不优美,但是最实用):
(文章后面下载部分会给出一个实例工程可以快速创建出上述各种对话框)
返回目录
2. 关于ShowDialog方法
OK,创建好对话框后,就是怎么显示的问题了。这里还是有一些问题的需要警惕的。
在Windows Forms框架中,显示对话框窗体的方法:Form.ShowDialog有一个可以指定窗体所有者Owner的重载:
public DialogResult ShowDialog(IWin32Window owner);
Form类型也继承自IWin32Window接口。所以通过这个方法我们可以很快得显示一个对话框并且设置它的Owner。
而WPF中的窗体:Window类型并没有提供这样的重载,它的ShowDialog方法只有这样一个原型:
public bool? ShowDialog();
于是开发者调用ShowDialog时往往会直接忘记设置对话框的Owner属性,这样的后果是什么呢?我们慢慢来演示。
比如我们已经创建好了一个对话框,然后在主窗体里需要按照模式对话框显示,但是没有设置Owner直接调用ShowDialog:
new MyDialog().ShowDialog();
结果:
OK,看起来不错,对话框显示在主窗体上面,同时对话框不关闭主窗体无法获得焦点。
不过当你在任务栏中点击主窗体的图标后,你会发现,这个对话框会显示在主窗体之后了:
而且此时主窗体仍无法获得焦点,只有关闭后面的对话框才可以。
那么问题是当你把主窗体最大化后,再点任务栏中的主窗体图标,对话框没了,现在的问题就是由于主窗体是最大化状态,你根本没把点到也不可能关闭背后的对话框!而主窗体无法获得焦点没法点,程序就这样明明没死但是因无法操作而完蛋了。(如果WindowStyle不是ToolWindow的对话框,此时可以通过切换其他窗口或再次点击程序任务栏图标对话框即可再次出现在主窗体之上,如果没法出现,程序只能通过任务管理器强制结束。)
因此不管上面的问题你怎么看,相信谁也不想因为这种小问题而惹恼用户,那么乖乖地设置Owner吧,像这样:
var dlg = new MyDialog();
dlg.Owner = this;
dlg.ShowDialog();
这样不仅不会由上面的问题,当模式对话框没有关闭但用户尝试点击主窗体时,对话框还会不停得闪动来提示用户先完成对话框的工作。
当然,对于上面讲的WPF的ShowDialog没有提供快速设置Owner属性的重载,我们可以写一个扩展方法。一个可以设置Owner,另一个会自动把当前应用程序的主窗体(通过Application.Current.MainWindow)作为对话框的Owner并显示对话框。
static class WindowExtension
{
public static void ShowDialog(this Window win, Window owner)
{
win.Owner = owner;
win.ShowDialog();
}
public static void ShowDialogEx(this Window win)
{
win.ShowDialog(Application.Current.MainWindow);
}
}
这样的话,使用起来就更方便了:
new MyDialog().ShowDialogEx();
//或者
new MyDialog().ShowDialog(this);
WPF:更好得理解对话框和ShowDialog方法 .相关推荐
- 改善WPF应用程序性能的10大方法(转)
细数改善WPF应用程序性能的10大方法 2010年11月16日00:05 it168网站原创 作者:IT168 黄永兵 编辑:胡铭娅 评论:0条 本文Tag: ASP.NET WPF .NET ...
- 细数改善WPF应用程序性能的10大方法
WPF(Windows Presentation Foundation)应用程序在没有图形加速设备的机器上运行速度很慢是个公开的秘密,给用户的感觉是它太吃资源了,WPF程序的性能和硬件确实有很大的关系 ...
- 汇编程序-更灵活的定位内存地址方法
汇编程序-更灵活的定位内存地址方法 如何灵活运用定位内存的方法呢?在之后,我们将列出几个实际例子.通过例子,展示定位内存的一些方法,熟悉和提升我们对汇编程序的理解. 大小写转化(1) 通过上面的汇编程 ...
- 神经机器阅读理解最新综述:方法和趋势
作者丨刘姗姗 学校丨国防科技大学 研究方向丨自然语言处理 近年来,基于深度学习方法的机器阅读理解受到了广泛的关注.近日,来自国防科技大学的团队在arXiv上发布了预印版综述文章 Neural Mach ...
- 小学阅读方法六种_小学语文重难点|阅读理解的解答技巧+方法(合集)
阅读理解,一直是小学阶段孩子们除写作以外最头疼的部分,很多孩子每次考虑的时候阅读理解都会被扣掉大量的分数.那么孩子们应该如何更好的进行阅读和理解呢?今天我们就来为孩子们分享一些关于小学语文阅读理解的解 ...
- Android-- Dialog对话框的使用方法
Activities提供了一种方便管理的创建.保存.回复的对话框机制,例如onCreateDialog(int),onPrepareDialog(int, Dialog),showDialog(int ...
- C# 按Button弹出新的窗体 Show()方法 和 ShowDialog()方法
在做串口通信程序时,有个想法,当点击串口设置按钮时,弹出一个新的窗口,可以设置串口相关信息,如何实现这一操作呢? 1 新建一个项目,窗体为form1 2 选择项目名称,单击右键,选择[添加]→[窗体] ...
- 九种js弹出对话框的实现方法
原文地址:九种js弹出对话框的实现方法 作者:哼哼哈哈 网络编程中,经常要用到 js弹出对话框 http://www.cnxwlm.com/network-biancheng/baidu_313/来增 ...
- 上网聊天更顺畅MSN常见故障解决方法(转)
上网聊天更顺畅MSN常见故障解决方法(转)[@more@] MSN这款即时通信工具功能强大.操作便捷,但复杂的网络环境难免会造成这样那样的问题,让使用者摸不着头脑,如何解决这些难题呢?下面就带大家一起 ...
- 神经网络训练中batch的作用(从更高角度理解)
1.什么是batch batch,翻译成汉语为批(一批一批的批).在神经网络模型训练时,比如有1000个样本,把这些样本分为10批,就是10个batch.每个批(batch)的大小为100,就是bat ...
最新文章
- 技术图文:如何利用C# 实现 Prim 最小生成树算法?
- python 对字典排序
- mysql为什么用索引_MySql为什么使用B+树做索引
- 浅谈runtime运行时机制
- linux下面的时间设置
- 申请域名的理由_申请网站名称和域名注册为商标的重要性增加了吗?原因?
- Linux 命令集合
- ARM Linux 3.x的设备树(Device Tree)
- Javascript 第七天 笔记
- Network Emulation(网格模拟)
- linux hive的作用,Hive的基本应用 - Hadoop和Hive的实践应用_服务器应用_Linux公社-Linux系统门户网站...
- ios中amplify配置configure_Asp.netCore3.0 简单的webapi接口 (中)
- githubRank: Github 项目和用户排行榜
- Java线程与Android线程,Android线程篇(三):深入理解Java线程池(一)
- matlab图像粘连计数,Matlab图像处理在水稻谷粒计数中的应用
- Python实现基于VGG16迁移学习实现手写数字识别
- “一晚上” 拿到阿里offer的详细准备经历
- 数字图像处理——灰度变换
- react-ative安装expo-linking后运行报错
- Python爬虫 - 抓取divnil动漫妹子图
热门文章
- 【车间调度】基于matlab粒子群算法求解生产调度问题【含Matlab源码 485期】
- 【滤波器】基于matlab GUI低通+带通+高通FIR与IIR滤波器设计【含Matlab源码 360期】
- 【优化预测】基于matlab鲸鱼算法优化LSTM预测【含Matlab源码 105期】
- 青县计算机学校,青县将建设新学校(中小学各一所)今年3月开工,明年即可完工!...
- docker配置 nacos_Docker下配置nacos
- 负载均衡策略_高负荷小区负载均衡策略建议
- 南昌计算机学校哪家最可靠,南昌问题孩子管教学校哪家靠谱
- 恩佐盒子服务器维护,恩佐宝盒有苹果版吗
- 人工智能领域的新秀——Get智能写作
- div contenteditable=true各个浏览器上的解析