mobileControls与移动控件适配

此配置节的作用在于指定各种控件在不同类型的移动设备显示的适配器,以达到适应各种设备不同的展示形式。例子如下,

<mobileControls sessionStateHistorySize="6"

cookielessDataDictionaryType="System.Web.Mobile.CookielessData">

<device name="XhtmlDeviceAdapters"

predicateClass="System.Web.UI.MobileControls.Adapters.XhtmlAdapters.XhtmlPageAdapter"

predicateMethod="DeviceQualifies"

pageAdapter="System.Web.UI.MobileControls.Adapters.XhtmlAdapters.XhtmlPageAdapter">

<control name="System.Web.UI.MobileControls.Panel"

adapter="System.Web.UI.MobileControls.Adapters.XhtmlAdapters.XhtmlPanelAdapter" />

<!--其他控件-->

</device>

<device name="HtmlDeviceAdapters"

predicateClass="System.Web.UI.MobileControls.Adapters.HtmlPageAdapter"

predicateMethod="DeviceQualifies"

pageAdapter="System.Web.UI.MobileControls.Adapters.HtmlPageAdapter">

<control name="System.Web.UI.MobileControls.Panel"

adapter="System.Web.UI.MobileControls.Adapters.HtmlPanelAdapter" />

<control name="System.Web.UI.MobileControls.Form"

adapter="System.Web.UI.MobileControls.Adapters.HtmlFormAdapter" />

<control name="System.Web.UI.MobileControls.TextBox"

adapter="System.Web.UI.MobileControls.Adapters.HtmlTextBoxAdapter" />

<!--其他控件-->

</device>

<device name="UpWmlDeviceAdapters"

inheritsFrom="WmlDeviceAdapters"

predicateClass="System.Web.UI.MobileControls.Adapters.UpWmlPageAdapter"

predicateMethod="DeviceQualifies"

pageAdapter="System.Web.UI.MobileControls.Adapters.UpWmlPageAdapter">

</device>

<device name="WmlDeviceAdapters"

predicateClass="System.Web.UI.MobileControls.Adapters.WmlPageAdapter"

predicateMethod="DeviceQualifies"

pageAdapter="System.Web.UI.MobileControls.Adapters.WmlPageAdapter">

<control name="System.Web.UI.MobileControls.Panel"

adapter="System.Web.UI.MobileControls.Adapters.WmlPanelAdapter" />

<control name="System.Web.UI.MobileControls.Form"

adapter="System.Web.UI.MobileControls.Adapters.WmlFormAdapter" />

<!--其他控件-->

</device>

<device name="ChtmlDeviceAdapters"

inheritsFrom="HtmlDeviceAdapters"

predicateClass="System.Web.UI.MobileControls.Adapters.ChtmlPageAdapter"

predicateMethod="DeviceQualifies"

pageAdapter="System.Web.UI.MobileControls.Adapters.ChtmlPageAdapter">

<control name="System.Web.UI.MobileControls.Form"

adapter="System.Web.UI.MobileControls.Adapters.ChtmlFormAdapter" />

<control name="System.Web.UI.MobileControls.Calendar"

adapter="System.Web.UI.MobileControls.Adapters.ChtmlCalendarAdapter" />

<!--其他控件-->

</device>

</mobileControls>

实际上这也是本配置节的默认配置的精简版。

各个节点和属性含义如下

<mobileControls

--指定移动控件是否可以具有自定义特性。

allowCustomAttributes="true|false"

--定义字典类的类型,该类维护无 Cookie 的 Forms 身份验证的密钥。

cookielessDataDictionaryType="System.Web.Mobile.CookielessData"

--定义用于在服务器会话中保存应用程序视图状态的历史记录的大小。

sessionStateHistorySize="number">

<!—适配器集-->

<device

name="String"

--指定该设备适配器集必须继承的设备适配器集。

inheritsFrom="String" "

--为适配器集指定页适配器的类类型。

pageAdapter="String"

--指定提供计算器谓词的类类型。

predicateClass="String"

--指定提供计算器谓词的方法。

predicateMethod="String>

<control

--控件的完全限定名称。

name="String"

--设备适配器的完全限定名称。

adapter="String" />

</device>

<device...>...</device>

</mobileControls>

device节点中,通过predicateClass中指定的类里面的predicateMethod指定的方法来判定当前这个设备是否适用于本适配器。这里感觉就和deviefilter识别相当类似,下面则是ChtmlPageAdapter的谓词方法

了解设备适配器选择过程

下面的过程描述如何选择页的设备适配器集:

  1. 按照 Web.config 文件中 <device> 节的定义,ASP.NET 循环访问设备适配器集的集合。 首先检查与所请求的页最接近的 Web.config 文件,然后依次检查在配置层次结构中处于更高位置的各个 Web.config 文件。 最后检查 Machine.config 文件。
  2. 使用 predicateClass 和 predicateMethod 特性来计算每个设备适配器集的关联谓词。
  3. 每个谓词使用所提供的 HttpContext 对象来检查目标设备的设备功能,并返回 true 或 false 来指示设备适配器集是否适用。
  4. 只要有任何谓词返回 true,即认为该设备适配器集是被选定的。 此时,系统使用 <device> 元素的 pageAdapter 特性来确定创建哪个类的实例并创建适配器。
  5. 如果 Web.config 文件中的谓词都没有返回 true,则将为父目录的 Web.config 文件中的设备适配器集重复此过程。

对于每一个控件,将调用页来提供指定控件类型的设备适配器。 ASP.NET 使用以下步骤来选择适当的控件适配器:

  1. 所使用的设备适配器集与为页的设备适配器选择的适配器集相同。
  2. 如果设备适配器集包含直接将控件类映射到设备适配器类的 <control> 元素,则将创建指定适配器类的实例。
  3. 如果无法直接映射设备适配器集,则将为控件创建基类的新实例。
    此过程将一直重复,直至达到基类 Control 为止。 如果在任何时候找到了直接映射,则将创建指定设备适配器类的新实例。
  4. 如果仍未找到映射,并且设备适配器集从其他适配器集继承,则将为父适配器集重复适配器选择步骤。 此过程将沿着适配器集的层次结构向上执行,直至找到映射。

查找的结果会缓存起来,因此只需要为第一个相关控件执行一次指定的查找。 上述的行为将保留下来。

在 ASP.NET 移动控件及其关联的适配器的生命周期中发生两种类型的交互:控件和设备适配器之间的交互以及页和页适配器之间的交互。

控件和控件设备适配器

在移动控件的生命周期中,在控件及其关联的设备适配器之间发生以下交互:

  1. ASP.NET 先检查缓存中是否存在页的副本。 如果存在,则将缓存的页发送到客户端。 有关缓存的更多信息,请参见移动文本编写器呈现的最佳做法的"输出缓存"一节。
  2. 创建控件。 当首次尝试访问控件的 Adapter 属性时,将选择控件适配器并创建它的一个新实例,如适配器映射中的"了解设备适配器选择过程"一节所述。
    当创建新适配器时,将设置控件设备适配器的 Control
  3. 如果页进行了缓存,则该页将调用适配器以确定缓存是否需要通过任何附加头有所变化。
  4. 调用控件的 OnInit 方法。 MobileControl 基类的实现调用控件设备适配器的 OnInit 方法。
  5. 如果存在控件的私有视图状态,则将加载该状态。 如果设备适配器存储了控件的任何设备特定的状态,则 LoadPrivateViewState 方法的 MobileControl 基类实现将调用控件设备适配器的 LoadAdapterState 方法。
  6. 调用控件的 OnLoad 方法。 MobileControl 基类的实现调用控件设备适配器的 OnLoad 方法。
  7. 如果控件实现 IPostBackEventHandler 接口并接收回发事件,则调用控件的 RaisePostBackEvent 方法。 如果发送到控件的事件能够根据目标设备有所变化,则此方法的控件实现将调用控件设备适配器的 HandlePostBackEvent 方法。 HandlePostBackEvent 方法返回 true 或 false,指示设备适配器是否已处理事件。
  8. 如果适用,保存控件的私有视图状态。 如果适配器需要存储控件的任何设备特定的状态,则 SavePrivateViewState 方法的 MobileControl 基类实现将调用控件设备适配器的 SaveAdapterState 方法。
  9. 调用控件的 OnPreRender 方法。 MobileControl 基类的实现调用控件设备适配器的 OnPreRender 方法。
  10. 调用控件的 Render 方法。 MobileControl 基类的实现调用控件适配器的 Render 方法。
  11. 调用控件的 OnUnload 方法。 MobileControl 基类的实现调用控件设备适配器的 OnUnload 方法。

页和页适配器

虽然 MobilePage 类从 .NET Framework Page 类(而不是 MobileControl 类)继承,但 MobilePage 类与适配器相关的行为非常类似于 MobileControl 类的行为。

ASP.NET 中的移动页适配器(例如 ChtmlPageAdapterHtmlPageAdapterWmlPageAdapter 或 XhtmlPageAdapter)实现 IPageAdapter 接口(该接口本身实现 IControlAdapter 接口)。 因此,页适配器的大部分生命周期类似于控件适配器的生命周期。 移动页及其设备适配器的交互特定于 Page 类,并且在它们的生命周期中经历以下步骤:

  1. ASP.NET 创建一个页。 当首次尝试访问页的 Adapter 属性时,将选择页适配器并创建它的一个实例,如适配器映射中的"了解设备适配器选择过程"一节所述。 当创建适配器时,将设置页适配器的 Page 属性。
  2. 调用页的 OnInit 方法。 MobilePage 基类的实现调用页适配器的 OnInit 方法。
  3. 调用页的 OnDeviceCustomize 方法。 MobilePage 基类的实现调用页适配器的 OnDeviceCustomize 方法。
  4. 若要确定页的回发模式(如果适用),则 MobilePage 基类将调用页适配器的 DeterminePostBackMode 方法。 此方法可以检查和修改请求变量。 此方法还负责将任何保持的视图状态信息转换回窗体变量(如果该信息尚未在某个变量中)。
  5. 如果适用,加载页的私有视图状态。 如果适配器存储页的任何特定于设备的视图状态,则 MobilePage 基类调用页适配器的 LoadAdapterState 方法。
  6. 调用页的 OnLoad 方法。 MobilePage 基类的实现调用页适配器的 OnLoad 方法。
  7. 如果适用,保存页的私有视图状态。 如果适配器需要存储页的任何特定于设备的视图状态,则 MobilePage 基类调用页适配器的 SaveAdapterState 方法。
  8. MobilePage 基类调用页适配器的 SaveViewState 方法。 此方法负责确保作为参数传入的状态被序列化到写入的页。
  9. 在分页过程中,MobilePage 基类访问页适配器的 OptimumPageWeight 属性。 适配器返回适合目标设备的页权重。
  10. 调用页的 OnPreRender 方法。 MobilePage 基类的实现调用页适配器的 OnPreRender 方法。
  11. 创建一个编写器实例用于捕获页输出。 MobilePage 基类调用页适配器的 CreateTextWriter 方法,该方法必须返回特定于目标的文本编写器。
  12. 调用页的 Render 方法。 MobilePage 基类的实现调用页适配器的 Render 方法。 在呈现过程的某些特定时刻,适配器还负责通过页的 ClientViewState 属性访问并编写页的私有视图状态。
  13. 调用页的 OnUnload 方法。 MobilePage 基类的实现调用页适配器的 OnUnload 方法。

大致看了一下上述的流程和网上的源码,感觉每个移动控件的生命周期只是定立了一个基本的套路,并没有具体实现控件在某个具体生命周期内该做的事情,比如拿Calendar控件的渲染Render来说

它直接调用了基类的Render方法,而这个Render调用了OnRender

这里的Adapter只是一个接口,是从Page中获取的Adapter,具体的Adapter是从web.config中配置再筛选可得,那就看看具体某个ControlAdapter的Render方法,这里拿ChtmlCalendarAdapter为例,内容过长只截取方法头和部分代码

看了就知道这确实是实际的渲染控件的代码。虽然感觉这种方式怪怪的,可能也是适配器的作用,但是它确确实实能达到同一个控件在不同设备上呈现不同样式的。

参考

适配器映射

来自 <https://msdn.microsoft.com/zh-cn/library/w5b9y36y(v=vs.100).aspx>

适配器类型

来自 <https://msdn.microsoft.com/zh-cn/library/99tteheb(v=vs.100).aspx>

适配器与 ASP.NET 的交互

来自 <https://msdn.microsoft.com/zh-cn/library/w5thxd3s(v=vs.100).aspx>

移动文本编写器呈现的最佳做法

来自 <https://msdn.microsoft.com/zh-cn/library/aa2w58cf(v=vs.100).aspx>

分页支持

来自 <https://msdn.microsoft.com/zh-cn/library/hhfw2x5a(v=vs.100).aspx>

设备模板支持

来自 <https://msdn.microsoft.com/zh-cn/library/yt1b020d(v=vs.100).aspx>

实现模板呈现

来自 <https://msdn.microsoft.com/zh-cn/library/ah665120(v=vs.100).aspx>

时间: 11-01

mobileControls与移动控件适配的相关文章

前端页面适配的rem换算

为什么要使用rem 之前有些适配做法,是通过js动态计算viewport的缩放值(initial-scale). 例如以屏幕320像素为基准,设置1,那屏幕375像素就是375/320=1.18以此类推. 但直接这样强制页面缩放过于粗暴,会导致页面图片文字失真模糊. Px是相对固定单位,字号大小直接被定死,所以用户无法根据自己设置的浏览器字号而缩放,em和rem虽然都是相对单位,但em是相对于它的父元素的font-size,页面层级越深,em的换算就越复杂,而rem是直接相对于根元素,这就避开了

登录界面、AutoUtils 屏幕适配、自定义Edittext(显示密码可见和一键清空)和 TextInputLayout的使用。

登录界面: AutoUtils自动屏幕适配: AutoUtils屏幕适配使用的方法 : 1.将AutoUtils类复制到要适配的项目中: 2.在程序的入口(清单文件filter):super.onCreate(savedInstanceState);//屏幕适配,这里是以720*1280分辨率为基准的适配AutoUtils.setSize(this, false, 720, 1280); * 这里我们UI是以1920*1280分辨率做图的,并且是横屏显示:AutoUtils.setSize(th

Android 屏幕适配问题分析

一.屏幕分辨率.大小及相关单位介绍 Android categorizes device screens using two general properties: size and density.There are four generalized sizes: small, normal, large, xlarge:And four generalized densities: low (ldpi 0.75), medium (mdpi 1.0 baseline), high (hdpi

适配iOS10以及Xcode8-b

现在在苹果的官网上,我们已经可以下载到Xcode8的GM版本了,加上9.14日凌晨,苹果就要正式推出iOS10系统的推送了,在此之际,iOS10的适配已经迫在眉睫啦,不知道Xcode8 beat版本,童鞋们有木有下载过来试试呢?就我的使用来说,总体觉得苹果还是坑不断,但是也在一直进步的啦.下面我就来说说,iOS10的适配以及Xcode8使用上的一些注意点. 一.证书管理 用Xcode8打开工程后,比较明显的就是下图了,这个是苹果的新特性,可以帮助我们自动管理证书.建议大家勾选这个Automati

移动端适配方案研究

初次接触移动端的时候,以为终于可以不用像pc那样考虑令人头疼的ie浏览器兼容问题,有强大的css3的帮助,可以随心所欲..可是后来才发现原来移动端各种层次不齐的终端更会让人抓耳挠腮,同样的页面在不同的手机上显示的完全不一样的效果,于是抛开功能,页面适配性也成了一个大的课题. 说到移动端,下面这一行代码大家一定不陌生: <meta name="viewport" content="width=device-width, initial-scale=1, maximum-s

升级Xcode7之后的适配问题(插件、ATS等)

一.插件失效 1. 首先查看 Xcode 的 UUID,在终端执行 defaults read /Applications/Xcode.app/Contents/Info DVTPlugInCompatibilityUUID 会得到一串 UUID 码 2. 找到 Xcode 插件所在的目录 ~/Library/Application Support/Developer/Shared/Xcode/Plug-ins 选择已安装的插件如:VVDocumenter-Xcode,右键显示包内容,找到 in

操作系统: 最佳适配算法和邻近适配算法的模拟实现(内存分配算法)

实现动态分区的分配算法. (1) 最佳适配算法:选择内存空闲块中最适合进程大小的块分配. (2) 邻近适配算法:从上一次分配的地址开始查找符合要求的块,所查找到的第一个满足要求的空闲块就分配给进程. 模拟添加进程的时候,假定内存是一块完整的空闲区,对于算法(1)来说,分配的时候遍历所有的空闲内存块,找出其中最适合的一块,注意此时内存分区的总块数可能已经发生了变化: 对于算法(2)来说,则需要从上次分配的内存块(使用变量记录即可)接着向下找到第一个满足条件的块即可,内存分区的总块可能也已经发生了变

APP适配IOS8,iPhone6和Plus截图简要说明

有幸在9月25日拿到了iP6和iP6 Plus的真机,恰好又要做适配APP的工作(从iphone5上适配到iphone6和ip6 plus上),所以在真机上研究了下苹果官方在不同分辨率下对系统APP所做的适配.同时在网上也没找到相关的真机对比截图说明什么的,又有朋友问我要IP6和PLUS的真机截图回去自己研究,既然这样,那么干嘛不利用自己已有的资源,让更多的设计师受益呢?所以那就说点什么吧,抛砖引玉,希望大家可以共同研究,少走些弯路,共同成长. 之前看过@jingdesign 的关于适配ip6的

纯代码 自动屏幕适配iPhone

代码判断,你也可以用xib自带的自动布局选项 我是用的纯代码写的 纯代码 自动屏幕适配iPhone,布布扣,bubuko.com

dubbo之日志适配及访问日志

日志适配 自 2.2.1 开始,dubbo 开始内置 log4j.slf4j.jcl.jdk 这些日志框架的适配 1,也可以通过以下方式显示配置日志输出策略: 命令行 java -Ddubbo.application.logger=log4j 在 dubbo.properties 中指定 dubbo.application.logger=log4j 在 dubbo.xml 中配置 <dubbo:application logger="log4j" /> 访问日志 如果你想记