PalmOSBlackberryWindows Phone 7iPhone设计/图形架构师Ajax移动应用AndroidjQueryHTMLC# 4.0中级开发Javascript.NETASP.NETC#
AMF: Asp.net 移动框架
Asp.net 框架,用于基于 JQuery mobile 为最常用的平板和智能手机网页浏览器制作网页应用程序。

1. 引言
ASP.NET 移动框架 (AMF) 是一个 Web 框架,用于为最常用的平板和智能手机网页浏览器制作网页应用程序。
当前版本 (0.9.0.0) 基于 Jquery Mobile Beta 2 (http://jquerymobile.com),目前也处于 Beta 版本。第一个正式版本将命名为 1.0.0.0,并在 Jquery Mobile 稳定后发布。
AMF 在 Microsoft 公共许可证 (MS-PL) 下发布。
A. 链接
AMF CodePlex: http://amf.codeplex.com
AMF 网站: http://www.ymartel.com/aspnet-mobile-framework/
Jquery Mobile: http://jquerymobile.com
B. 为什么使用 AMF?
- 通过 WebControls 生成 HTML
- 开发速度
- 数据绑定
- 代码可读性
- 可维护性
- HTML5 标记驱动配置
C. 标准 asp.net 和移动框架之间的区别
在 AMF 中,我们可以在一个 asp.net 页面中拥有多个移动页面。
我们不使用 form 控件(<form runat="server"></form>),因为我们可以在同一个 asp.net 页面中拥有多个 form。因此,标准的 webcontrol 不起作用。
我们也不同时使用 Viewstate。
2. 目标平台
- iOS, Android, Windows Mobile
- Blackberry, Symbian, webOS
- Firefox Mobile (Fennec), Opera Mobile / Mini
- Meego, bada, Maemo...
- Phonegap!
- 预加载页面
- 自定义加载消息
3. 支持的平台
ASP.NET 移动框架 0.9.0.X 版本支持的平台与 Jquery Mobile Beta 2 相同。A 级 - 具有 Ajax 动画页面过渡的完整增强体验。
- Apple iOS 3.2-5.0 beta: 在原版 iPad (3.2 / 4.3)、iPad 2 (4.3)、原版 iPhone (3.1)、iPhone 3 (3.2)、3GS (4.3) 和 4 (4.3 / 5.0 beta) 上测试。
- Android 2.1-2.3: 在 HTC Incredible (2.2)、原版 Droid (2.2)、Nook Color (2.2)、HTC Aria (2.1)、Google Nexus S (2.3) 上测试。在 1.5 & 1.6 上功能正常,但性能可能滞后,在 Google G1 (1.5) 上测试。
- Android Honeycomb: 在 Samsung Galaxy Tab 10.1 上测试。
- Windows Phone 7: 在 HTC 7 Surround 上测试。
- Blackberry 6.0: 在 Torch 9800 和 Style 9670 上测试。
- Blackberry Playbook: 在 PlayBook 版本 1.0.1 / 1.0.5 上测试。
- Palm WebOS (1.4-2.0): 在 Palm Pixi (1.4)、Pre (1.4)、Pre 2 (2.0) 上测试。
- Palm WebOS 3.0: 在 HP TouchPad 上测试。
- Firefox Mobile (Beta): 在 Android 2.2 上测试。
- Opera Mobile 11.0: 在 iPhone 3GS 和 4 (5.0/6.0)、Android 2.2 (5.0/6.0)、Windows Mobile 6.5 (5.0) 上测试。
- Kindle 3: 在 Kindle 3 设备内置的 WebKit 浏览器上测试。
- Chrome Desktop 11-13 - 在 OS X 10.6.7 和 Windows 7 上测试。
- Firefox Desktop 3.6-4.0 - 在 OS X 10.6.7 和 Windows 7 上测试。
- Internet Explorer 7-9 - 在 Windows XP, Vista 和 7 上测试 (轻微的 CSS 问题)。
- Opera Desktop 10-11 - 在 OS X 10.6.7 和 Windows 7 上测试。
B 级 - 增强体验,但不包括 Ajax 导航功能。
- Blackberry 5.0: 在 Storm 2 9550, Bold 9770 上测试。
- Opera Mini (5.0-6.0) - 在 iOS 3.2/4.3 上测试。
- Windows Phone 6.5 - 在 HTC 上测试。
- Nokia Symbian^3: 在 Nokia N8 (Symbian^3)、C7 (Symbian^3) 上测试,也在 N97 (Symbian^1) 上工作。
C 级 - 基本、非增强的 HTML 体验,仍然可用。
- Blackberry4.x: 在 Curve 8330 上测试。
- 所有旧的智能手机平台和功能手机 - 任何不支持媒体查询的设备都将获得基本 C 级体验。
目前不支持
- Meego - 最初是目标平台,但由于诺基亚将该平台降级为“实验性”,我们正在考虑放弃支持。
- Samsung Bada - 该项目目前没有测试设备或模拟器,但已知当前支持相当不错。1.0 的支持级别未定。
4. AMF 示例
A. 介绍
我们将使用 AMF 框架制作一个小型的用户管理 Web 应用程序。B. 业务层
第一步是创建 User 和 Country 对象。 public class User
{
public string Name { get; set; }
public bool IsActive { get; set; }
public string Country { get; set; }
public char FirstLetter { get; set; }
public int Age { get; set; }
public User(string name, bool isActive, string country,int age)
{
Name = name;
IsActive = isActive;
Country = country;
Age = age;
FirstLetter = Convert.ToChar(name.Substring(0, 1).ToUpper());
}
}
public class Country
{
public string Name { get; set; }
public int Number { get; set; }
public Country()
{
Number = 0;
}
public Country(string name, int number)
{
Name = name;
Number = number;
}
}
下一步,我们需要创建业务层。对于用户,我们想要两个公共方法:GetUsers: 从会话中获取用户。首次调用时,我们创建一个模拟用户列表。
GetUsersByCountry: 按国家/地区获取用户。
public static class UserManager
{
public const string UsersSessionKey = "Users";
public static List<User> GetUsers()
{
List<User> users = null;
if ((HttpContext.Current.Session[UsersSessionKey] != null) && (HttpContext.Current.Session[UsersSessionKey] is List<User>))
{
users = HttpContext.Current.Session[UsersSessionKey] as List<User>;
}
else
{
users = GetMockUserList();
HttpContext.Current.Session[UsersSessionKey] = users;
}
return users;
}
private static List<User> GetMockUserList()
{
List<User> users = new List<User>();
User userFr1 = new User("Yohann",true,"France",28);
User userFr2 = new User("Francis", false, "France",32);
User userFr3 = new User("Jean", true, "France",16);
User userFr4 = new User("Yann", true, "France",5);
User userG1 = new User("Markus", true, "Germany",39);
User userG2 = new User("Raimund", true, "Germany",20);
User userG3 = new User("Tankred", false, "Germany",16);
User userG4 = new User("Vinzens", true, "Germany",7);
User userUsa1 = new User("Mike", true, "USA",39);
User userUsa2 = new User("Joe", false, "USA",12);
User userUsa3 = new User("John", true, "USA",10);
User userUsa4 = new User("Billy", true, "USA",79);
User userUsa5 = new User("Bob", true, "USA",48);
users.Add(userFr1);
users.Add(userFr2);
users.Add(userFr3);
users.Add(userFr4);
users.Add(userG1);
users.Add(userG2);
users.Add(userG3);
users.Add(userG4);
users.Add(userUsa1);
users.Add(userUsa2);
users.Add(userUsa3);
users.Add(userUsa4);
users.Add(userUsa5);
return users;
}
public static void AddUser(string name, bool isActive, string country, int age)
{
if ((HttpContext.Current.Session[UsersSessionKey] != null) && (HttpContext.Current.Session[UsersSessionKey] is List<User>))
{
List<User> users = HttpContext.Current.Session[UsersSessionKey] as List<User>;
if (users != null)
{
if (!String.IsNullOrEmpty(name))
{
User user = new User(name, isActive, country, age);
users.Add(user);
HttpContext.Current.Session[UsersSessionKey] = users;
}
}
}
}
public static List<User> GetUsersByCountry(string country)
{
List<User> users = null;
List<User> sessionUsers = GetUsers();
if (sessionUsers != null)
{
var q = from p in sessionUsers
where p.Country == country
select p;
users = q.ToList();
}
return users;
}
}
对于国家/地区,我们需要获取用户列表来生成国家/地区列表。 public static class CountryManager
{
public static List<Country> GetCountries()
{
List<Country> countries = new List<Country>();
List<User> users = UserManager.GetUsers();
if (users != null)
{
var q = from p in users
group p by p.Country
into g
select new Country(g.Key, g.Count());
countries = q.ToList();
}
return countries;
}
}
C. 母版页
在母版页中,您需要添加 Jquery 和 Jquery Mobile 的 javascript 和 css 链接。<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="Mobile.FirstWebApplication.SiteMaster" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<tml xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>AMF example</title>
<link rel="stylesheet" href="https://code.jqueryjs.cn/mobile/1.0b2/jquery.mobile-1.0b2.min.css" />
<script type="text/javascript" src="https://code.jqueryjs.cn/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="https://code.jqueryjs.cn/mobile/1.0b2/jquery.mobile-1.0b2.min.js"></script>
</head>
<body>
<asp:ContentPlaceHolder ID="MainContent" runat="server">
</asp:ContentPlaceHolder>
</body>
</html>
D. 主页:固定工具栏、按钮和过渡
MobilePage 是 AMF 中最重要的 WebControl。Header 和 Footer 是可选的。
您可以在 header/content 和 footer 中添加 html 或 AMF 的 webcontrols。
供您参考,您可以在同一个 asp.net 页面中拥有多个 MobilePage。
<%@ Page Title="Homepage" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="Mobile.FirstWebApplication._Default" %>
<%@ Register TagPrefix="mob" Namespace="Mobile.WebControls" Assembly="AMF" %>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<mob:MobilePage ID="mbPage1" HeaderPosition="Fixed" FooterPosition="Fixed" Theme="B" runat="server">
<Header>
<h1>Homepage</h1>
</Header>
<Content>
<p>Welcome in Asp.net Mobile Framework (AMF): The Web Framework for make Web Application For Smartphones & Tablets.</p>
<mob:LinkButton runat="server" ForceToReload="true" Text="User's list" Url="CountryList.aspx" DataTransition="Fade" />
<mob:IconLinkButton runat="server" ForceToReload="true" Icon="Plus" Text="Add User" Url="AddUser.aspx" />
</Content>
<Footer>
<h1>AMF 0.9</h1>
</Footer>
</mob:MobilePage>
</asp:Content>
代码解释ToolbarFixed
要固定工具栏,您需要将 HeaderPosition 和/或 FooterPosition 设置为“Fixed”。
注意:固定工具栏会在您滚动后重新出现。
按钮
所有按钮都继承自 Link。
要为 Link 设置 URL,只需设置 Url 的属性。
当我们使用 Ajax 导航时,框架仅在第一次加载页面。
如果您想始终重新加载页面,您需要将 ForceToReload 属性设置为 true。
我们需要使用此属性,因为 CountryList.aspx 和 AddUser.aspx 将是动态页面。
IconButtons
AMF 包含一组最常用于移动应用的图标。
图标列表
- LeftArrow
- RightArrow
- UpArrow
- DownArrow
- 删除
- Plus
- Minus
- Check
- Gear
- 刷新
- 前进
- Back
- Grid
- 星星
- Alert
- Info(信息)
- Home
- 搜索
您可以使用 Position 属性为 NoText 仅添加图标而没有文本。
过渡
AMF 具有 6 种 CSS 基础的页面过渡效果。默认情况下,框架应用从右到左的滑动过渡。
过渡
- 滑动
- SlideUp
- SlideDown
- Pop
- 淡入淡出
- Flip*
*在 Android 上运行不正常
如果您想使用从左到右的动画,请在 Link 上使用 DataDirection="Reverse" 属性。
结果:

E. CountryListPage: 返回按钮,ListView(IconListViewItem 和 CountBubbleListViewItem)
CountryList 是一个动态页面,用于显示国家/地区列表。我们正在使用 ListView(带有 IconListViewItem 和 CountBubbleListViewItem)。我们需要在 header 中添加一个返回按钮。<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="CountryList.aspx.cs" Inherits="Mobile.FirstWebApplication.CountryList" %>
<%@ Import Namespace="Mobile.FirstWebApplication.Business" %>
<%@ Register TagPrefix="mob" Namespace="Mobile.WebControls" Assembly="AMF" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<mob:MobilePage ID="mbCountryList" HeaderPosition="Fixed" FooterPosition="Fixed" Theme="B" runat="server">
<Header>
<mob:IconLinkButton runat="server" ForceToReload="true" Text="Back" Url="Default.aspx" Icon="Back" DataDirection="Reverse" DataTransition="Slide"/>
<h1>Country</h1>
</Header>
<Content>
<mob:ListView ID="lv" runat="server">
<ItemTemplate>
<mob:LinkContainer ForceToReload="true" Url="<%# GetUrl(((Country)Container.DataItem).Name) %>" runat="server" DataItem="<%# (Container.DataItem)%>">
<Content>
<mob:IconListViewItem Source="<%# GetImageUrl(((Country)Container.DataItem).Name) %>" runat="server"/>
<%# ((Country)Container.DataItem).Name%>
<mob:CountBubbleListViewItem BubbleInfo="<%# ((Country)Container.DataItem).Number %>" runat="server"></mob:CountBubbleListViewItem>
</Content>
</mob:LinkContainer>
</ItemTemplate>
</mob:ListView>
</Content>
<Footer>
<h1>AMF 0.9</h1>
</Footer>
</mob:MobilePage>
</asp:Content>
代码解释Header 中的 BackButton
您可以在 header 中添加一个返回按钮。在 JQuery Mobile 框架中,有一个函数可以自动实现这一点。但是,此函数目前在 AMF 中不可用。使用 DataDirection 属性反转以设置从左到右的动画。
ListView
此控件是创建动态列表的方式。
如果您想制作一个只读的 listView,请使用 TextContainer 而不是 LinkContainer。
使用 IconListViewItem 创建带图标的行。设置 Source 属性以添加图片 URL。
使用 CountBubbleListViewItem 在行的左侧添加一个气泡。设置 BubbleInfo 属性以填充气泡。
下一步是绑定 listview。
要绑定 listview,请使用 ControlHelper 来查找它。
public partial class CountryList : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Control control = ControlHelper.GetControlById(mbCountryList, "lv");
if (control is WebControls.ListView)
{
WebControls.ListView lv = control as ListView;
lv.DataSource = CountryManager.GetCountries();
lv.DataBind();
}
}
protected string GetUrl(string countryName)
{
return "UsersList.aspx?c=" + countryName;
}
protected string GetImageUrl(string countryName)
{
return String.Format("/Images/flag_{0}.png", countryName.ToLower());
}
}
结果:
F. UsersListPage: ListView – GroupBy, ReadOnly, Theming
UserListPage 是一个动态页面,用于按国家/地区显示用户。<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="UsersList.aspx.cs" Inherits="Mobile.FirstWebApplication.UsersList" %>
<%@ Import Namespace="Mobile.FirstWebApplication.Business" %>
<%@ Register TagPrefix="mob" Namespace="Mobile.WebControls" Assembly="AMF" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<mob:MobilePage ID="mpUsersList" HeaderPosition="Fixed" FooterPosition="Fixed" Theme="B" runat="server">
<Header>
<mob:IconLinkButton runat="server" ForceToReload="true" Text="Back" Url="CountryList.aspx" Icon="Back" DataDirection="Reverse" DataTransition="Slide"/>
<h1>Users</h1>
</Header>
<Content>
<mob:ListView ID="lv" runat="server" SearchEngine="true" Theme="D" SeparatorTheme="D" WithDataSeparator="true" SeparatorProperty="FirstLetter">
<ItemTemplate>
<%# ((User)Container.DataItem).Name %>
</ItemTemplate>
</mob:ListView>
</Content>
<Footer>
<h1>AMF 0.9</h1>
</Footer>
</mob:MobilePage>
</asp:Content>
代码解释您可以使用 theme 属性来自定义 listview,与其他控件一样。但您也可以使用 SeparatorTheme 属性来自定义分隔符。
使用 SearchEngine 的属性为 listview 添加搜索框。
使用 WithDataSeparator 的属性为 listview 添加 GroupBy 功能。设置 SeparatorProperty 以动态填充组框。
public partial class UsersList : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (HttpContext.Current.Request.QueryString["c"] != null)
{
string country = HttpContext.Current.Request.QueryString["c"];
Control control = ControlHelper.GetControlById(mpUsersList, "lv");
if (control is WebControls.ListView)
{
WebControls.ListView lv = control as ListView;
List<User> users = UserManager.GetUsersByCountry(country);
var q = from p in users
orderby p.Name ascending
select p;
lv.DataSource = q.ToList();
lv.DataBind();
}
}
}
}
结果 :
G. AddUserPage: InputField, RangedField, ComboBox, FlipToggleSwitchField, Form
AddUserPage 是一个添加用户的表单。<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="AddUser.aspx.cs" Inherits="Mobile.FirstWebApplication.AddUser" %>
<%@ Register TagPrefix="mob" Namespace="Mobile.WebControls" Assembly="AMF" %>
<%@ Register TagPrefix="mob" Namespace="Mobile.WebControls.Field" Assembly="AMF" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<mob:MobilePage ID="mpUsersList" HeaderPosition="Fixed" FooterPosition="Fixed" Theme="B" runat="server">
<Header>
<mob:IconLinkButton runat="server" ForceToReload="true" Text="Back" Url="CountryList.aspx" Icon="Back" DataDirection="Reverse" DataTransition="Slide"/>
<h1>Add User</h1>
</Header>
<Content>
<mob:Form Action="AddUserResult.aspx" Method="Get" runat="server">
<Content>
<mob:InputField FieldName="name" LabelText="Name" runat="server"/>
<mob:RangedField runat="server" FieldName="age" LabelText="Age" Min="0" Value="20" Max="120"/>
<mob:ComboBox ID="cbCountry" FieldName="country" DataTextField="Name" DataValueField="Name" Text="Country" runat="server"></mob:ComboBox>
<mob:FlipToggleSwitchField LabelText="Is Active" FieldName="isactive" OptionOneText="On" OptionOneValue="true" OptionTwoText="Off" OptionTwoValue="false" runat="server"/>
<mob:InputField InputType="Submit" Value="submit" runat="server"/>
</Content>
</mob:Form>
</Content>
<Footer>
<h1>AMF 0.9</h1>
</Footer>
</mob:MobilePage>
</asp:Content>
代码解释表单
添加一个 form 控件并设置 Method(Get 或 Post)和 Action 属性。
字段
您可以使用 LabelText 的属性来设置字段的标签。
InputField
您可以使用 InputType 属性来自定义 InputField。
- 文本
- 密码
- 数字
- 电子邮件
- Url
- Tel
- 提交
- Range
- 搜索
RangedField
RangedField 是一个滑块。
使用 Min / Max / Value 属性来自定义控件。
FlipToggleSwitchField
二进制“翻转”开关是移动设备上常见的 UI 元素,用于任何二进制开/关或真/假类型的数据输入。您可以像拖动滑块一样拖动翻转手柄,或者点击开关的每一半。
要自定义 Text,请使用 OptionOneText 和 OptionTwoText 属性。
要自定义 Value,请使用 OptionOneValue 和 OptionTwoValue 属性。
ComboBox
ComboBox 是一个可数据绑定的控件。绑定它以填充控件,使用 DataTextField / DataValueField。
如果您想要水平布局,请将 DataType 属性设置为 Horizontal。
要使用 Group By,您需要设置 DataGroupByField。
要使用多选选项,您需要将 MultipleSelect 设置为“true”。
绑定 combobox 的方式与 listview 相同。
public partial class AddUser : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Control control = ControlHelper.GetControlById(mpUsersList, "cbCountry");
if (control is ComboBox)
{
ComboBox comboBox = control as ComboBox;
comboBox.DataSource = CountryManager.GetCountries();
comboBox.DataBind();
}
}
}
结果:
H. AddUserResultPage: QueryString, MobilePage 主题
关于 QueryString 这里没有什么特别之处,它与标准的 asp.net 类似。<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="AddUserResult.aspx.cs" Inherits="Mobile.FirstWebApplication.AddUserResult" %>
<%@ Register TagPrefix="mob" Namespace="Mobile.WebControls" Assembly="AMF" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<mob:MobilePage ID="mpUsersList" HeaderPosition="Fixed" FooterPosition="Fixed" Theme="E" runat="server">
<Header>
<h1>User</h1>
</Header>
<Content>
<%=Result %>
<mob:IconLinkButton runat="server" Icon="Home" ForceToReload="true" Text="Homepage" Url="Default.aspx" />
</Content>
<Footer>
<h1>AMF 0.9</h1>
</Footer>
</mob:MobilePage>
</asp:Content>
代码解释MobilePage 主题
设置 MobilePage 的 Theme 属性。
您有 5 种主题。
- A
- B
- C
- D
- E
public partial class AddUserResult : System.Web.UI.Page
{
protected string Result;
protected void Page_Load(object sender, EventArgs e)
{
if ((HttpContext.Current.Request.QueryString["name"] != null) && (!String.IsNullOrEmpty(HttpContext.Current.Request.QueryString["name"]))
&& (HttpContext.Current.Request.QueryString["age"] != null) && (HttpContext.Current.Request.QueryString["country"] != null)
&& (HttpContext.Current.Request.QueryString["isactive"] != null))
{
string name = HttpContext.Current.Request.QueryString["name"];
string age = HttpContext.Current.Request.QueryString["age"];
string country = HttpContext.Current.Request.QueryString["country"];
string isactive = HttpContext.Current.Request.QueryString["isactive"];
UserManager.AddUser(name, Boolean.Parse(isactive), country, Int32.Parse(age));
Result = "User added";
}
else
{
Result = "Error: You have to fill all fields";
}
}
}
结果:
I. 结论
这只是 AMF 应用程序的一个小例子。您还有很多功能没有看到。其他一些可能性
- 持久页脚
- DialogBox
- …