ContentDialog是UWP开发中最常用的组件之一,一个体验良好的UWP应用很难避免不去使用它。博客园里也有许多的文章介绍如何来利用ContentDialog实现各种自定义样式的弹窗界面。不过实际上ContentDialog是一个令人又爱又恨的组件,今天我们就来说一下ContentDialog的缺点。

ContentDialog适合实现轻量级的UI需求,但在处理复杂UI需求时非常难用,例如说:

  • 多层级弹窗情况下的UI实现;
  • MVVM框架下的UI与业务逻辑的分离;
  • 需要弹窗关闭时返回用户操作结果的情况。

上述情况下,如果仍旧使用ContentDialog实现功能需求,会需要很多的代码来完成界面UI交互,这是多余且没有必要的。

多层级弹窗情况下的UI实现

先说第一种情况,多层级弹窗情况下的UI实现。假设我们有一个这样的需求:我们需要弹出一个窗口让用户修改应用设置,同时在用户修改后点击“保存设置”按钮时,弹出一个自定义UI的确认对话框询问用户是否确定保存。

怎么实现呢?很自然的想到,我们可以写两个ContentDialog,一个是设置界面的弹窗,另外一个是自定义UI的确认对话框。先弹出设置弹窗,点击“保存设置”时弹出确认对话框。听起来很完美,逻辑上也没有问题,编码运行一下呢,应用崩溃了...

这是个悲剧,看下VS的崩溃信息:

Only a single ContentDialog can be open at any time.

WTF!!! UWP应用同时只支持唤出一个ContentDialog 么?这也太坑了吧!

不要惊讶,事实上确实如此,关于这点,微软官方给出的解决方案是这样的:

Only one ContentDialog can be shown at a time. To chain together more than one ContentDialog, handle the Closing event of the first ContentDialog. In the Closing event handler, call ShowAsync on the second dialog to show it.

也就是说想要同时显示两个弹窗是不可能的,只能在第一个弹窗关闭后再来打开第二个。

那我们怎么让第二个弹窗出现时仍能保持第一个弹窗的工作状态呢?在这种情况下,我能想到两种解决方法,一是使用MessageDialog代替确认对话框(抛弃掉自定义UI),或者ContentDialog 内使用Frame做Page间导航,需要用户确认时,导航到确认页面。但是毫无疑问,这两种方法都极为影响用户体验。

MVVM框架下的UI与业务逻辑的分离

上面已经说到了ContentDialog 本身的限制使其很难实现复杂UI需求,而这种困难涉及到MVVM框架时情况会更为复杂一些。

我们知道一个好的基于MVVM框架构建的项目一定是结构清晰,UI交互与后台业务逻辑分离的完美状态。ContentDialog本身是一个UI组件,如果只是轻量级的UI需求,比如说只是自定义一个确认对话框,在MVVM项目中使用倒还行。但是如果是一个较为复杂的多(层级)弹窗交互需求,或者弹窗内涉及到导航服务,这种情况下,将View层与ViewModel层间的代码整理清楚就有些困难了。

在之前的一个项目中,我有遇到这样的情况,当时的选择是使用中间人模式,搭建了一个中介类。这个中介类对ViewModel层提供打开或跳转到指定弹窗页面的接口,对View层则实现调度ContentDialog,控制ContentDialog中Frame的页导航。

这样看起来好像也还不错,功能都实现了。但是缺点是仍旧是无法实现多层弹窗,同时要考虑ViewModel调用弹窗的多种情况,实现过程比较复杂,并不能算是一个优雅的解决方式。

需要弹窗关闭时返回用户操作结果的情况

在很多情况下,我们使用弹窗的交互方式并不仅仅是交互需求,而是业务逻辑上的需要,我们想要用户做出交互,并且返回交互结果给后台代码做进一步的处理。

举个例子说,我们做一个绘画应用,我们提供给用户一个调色板来选取画笔颜色,但是这个调色板常驻在画布有些过于侵占用户绘画空间,我们的理想状态是把它做成一个颜色选取弹窗。这个弹窗需要在用户点击更换颜色时弹出来让用户选择颜色,如果用户取消选取颜色则关闭不做任何操作,如果确定选取某一颜色则关闭并返回选取的颜色。如果用ContentDialog来做会怎么样呢?ContentDialog关闭时会返回一个类型为ContentDialogResult的对象来标识用户操作,其定义如下:

//
// 摘要:
// 指定用于指示 ContentDialog 的返回值的标识符。
public enum ContentDialogResult
{
//
// 摘要:
// 未点击按钮。
None = 0,
//
// 摘要:
// 主按钮由用户点击。
Primary = 1,
//
// 摘要:
// 辅助按钮由用户点击。
Secondary = 2
}

那么要实现上面的需求我们需要在ContentDialog中先暂存用户选取的颜色,在拿到返回结果后,如果值为ContentDialogResult.Primary则去取出暂存的颜色,否则不做任何处理。

听起来这已经是个完美的方案了,但是还是有个大问题:我们选取颜色是在一个颜色盘上点击想要的颜色的位置取色,而ContentDialog的返回结果是依赖于点击预定义的几个按钮(PrimaryButton/SecondaryButton/CloseButton),这种情况下,对于UI交互的限制非常大,我们无法实现在颜色盘上取色后立即关闭弹窗,并且返回结果。

结尾

说了这么多,那么有没有一个完美的解决方案呢?你问我有没有,肯定是有的啊!请看下图!

ContentDialog的内部实现其实是依赖Popup,这就让我有了一个大胆的想法,我们程序员最爱干的事情是什么?造轮子呀!ContentDialog不好用,造个好用的新轮子呀!

接下来几篇博文来教大家如何造一个好用的,适用于MVVM框架的弹窗层组件。有兴趣的可以先看一下我的开源项目HHChaosToolkit中的Picker部分(GitHub链接点这里)。

好的,本篇博文到此结束,不知道大家有没有收获,谢谢大家!

[UWP]不那么好用的ContentDialog的更多相关文章

  1. [UWP]使用Popup构建UWP Picker

    在上一篇博文<[UWP]不那么好用的ContentDialog>中我们讲到了ContentDialog在复杂场景下使用的几个令人头疼的弊端.那么,就让我们在这篇博文里开始愉快的造轮子之旅吧 ...

  2. xamarin UWP中MessageDialog与ContentDialog的区别

    MessageDialog与ContentDialog的异同点解析: 相同点一:都是uwp应用上的一个弹窗控件.都能做为弹出应用. 相异点一:所在命名空间不同,MessageDialog在Window ...

  3. win10 uwp ContentDialog 点确定不关闭

    微软的ContentDialog不是一直有,而是UWP新的,可以使用Content放用户控件,使用很好,但是一点不好的是,默认的一点击下面按钮就会退出. 我们有时候需要ContentDialog用户输 ...

  4. uwp - ContentDialog - 自定义仿iphone提示框,提示框美化

    原文:uwp - ContentDialog - 自定义仿iphone提示框,提示框美化 为了实现我想要的效果花费了我很长时间,唉,当初英语不好好学,翻官网翻了半天才找到,分享给刚入门的新手. 首先看 ...

  5. 张高兴的 UWP 开发笔记:定制 ContentDialog 样式

    我需要一个背景透明的 ContentDialog,像下图一样.如何定制?写了一个简单的示例(https://github.com/ZhangGaoxing/uwp-demo/tree/master/C ...

  6. win10 UWP MessageDialog 和 ContentDialog

    我之前开发一个软件 winMarkdown,这个软件在关闭需要提示用户还没有保存东西,需要保存,如果用户选择退出,那么把数据存放. 在Metro程序中,没有传统的窗口,当我们要用需要交互的消息提示时, ...

  7. Windows UWP开发系列 – MessageDialog 和 ContentDialog

    MessageDialog 在Metro程序中,没有传统的窗口,当我们要用需要交互的消息提示时,在Win8时代,引入了一个MessageDialog来取代常用的MessageBox.使用方法如下: p ...

  8. UWP开发必备以及常用知识点总结

    一直在学UWP,一直在写Code,自己到达了什么水平?还有多少东西需要学习才能独挡一面?我想对刚接触UWP的开发者都有这种困惑,偶尔停下来总结分析一下还是很有收获的! 以下内容是自己开发中经常遇到的一 ...

  9. Xamarin.Android和UWP之MVVM的简单使用(二)

    0x01 前言 前面一篇,Xamarin.Android和UWP之MVVM的简单使用(一),主要讲了MvvmLight的简单使用 这篇主要讲讲MvvmCross的简单使用,例子的话,还是和上篇的一样. ...

随机推荐

  1. linux使用privoxy将55转为http代理

    =============================================== 2018/3/21_第3次修改                       ccb_warlock 更新 ...

  2. Rabbitmq(4) 订阅模式

    p;发送者 x: 交换机 消息队列 c: 接收者 ------------------------------------------------------------------------ 发送 ...

  3. Spring中AOP主要用来做什么。Spring注入bean的方式。什么是IOC,什么是依赖注入

    Spring中主要用到的设计模式有工厂模式和代理模式. IOC:Inversion of Control控制反转,也叫依赖注入,通过 sessionfactory 去注入实例:IOC就是一个生产和管理 ...

  4. Spring.Net配置

    <?xml version="1.0" encoding="utf-8"?> <configuration>     <!--一定 ...

  5. 26.Hibernate-主键和映射.md

    目录 1.复合主键映射 [toc] 2.集合映射 2.1Set集合 2.2其他集合 [toc] 3.集合数据的读取 [toc] 4.一对多和多对一映射 4.1概念 4.2配置和开发 4.2.1关键点 ...

  6. jscript DOM操作

    \n 换行符 \b 空格 \r 回车 && 与 || 或 ! 非(取反) classList属性 classList 属性返回元素的类名,作为 DOMTokenList 对象. 该属性 ...

  7. win10版office365激活序列码

    win10版office365激活序列码(在别的地方找到一个) : NKGG6-WBPCC-HXWMY-6DQGJ-CPQVG 1.在线安装Office2016预览版后它是不会自动激活的,需在Offi ...

  8. Cobbler安装CentOS7系统时报错 What do you want do now?

    问题的根源: 在cobbler服务主机中执行了  createrepo --update  /var/www/cobbler/ks_mirror/CentOS-7-x86_64/ 导致的. cobbl ...

  9. tomcat7闪退

    问题是我昨天运行的好好的,今天加了些代码,tomcat7就会启动闪退.我把conf/server.xml中的<Context />去掉,tomcat又能正常启动! 那么问题出在哪里呢? 我 ...

  10. 网站开发,推荐使用SuperSlide 插件-Tab标签切换,图片滚动,无缝滚动,焦点图

    SuperSlide 致力于解决网站大部分特效展示问题,使网站代码规范整洁,方便维护更新.网站上常用的“焦点图/幻灯片”“Tab标签切换”“图片滚动”“无缝滚动”等只需要一个SuperSlide即可解 ...