每周源代码28 – ASP.NET MVC版iPhone

[原文发表地址] The Weekly Source Code 28 - iPhone with ASP.NET MVC Edition

[原文发表时间]June 9, 2008 11:33 PM

我最近对运用插件和其他工具来扩展应用程序这类越来越有兴趣了。image秉持着我一贯的要求阅读源代码以开发出更好的程序,亲爱的读者们,这里我为你们奉上第28篇“每周源代码”,之后还将源源不断地继续。

今天发布了iPhone 2.0,尽管我一直在尝试找到一个比Northwind更好的方案来展示它,我还是被Aaron的《用ASP.NET MVC玩转iPhone》一文感动到了。我酝酿着要写这样一篇博文已经有至少两个月了,不过现在他自己已经完成了,把我们大家都比下去了。掌声送给Aaron。

我主要是一个ASP.NET的开发者,一直用手机来游览一些信息,并且多年致力于此。差不多两年前,我做了DasBlog和这个网站,并且应用了一个手机版本。如果你通过黑莓或者移动Windows或其他小型设备访问hanselman.com,你会链接到有手机皮肤的同一个站点。我想把iPhone也加进来。

去年Al Pascual为Community Server添加了iPhone支持,通过将iPhone用户重定位到他的RSS feed,比起之前,提供了全新的简洁体验。

Steve Orr针对iPhone发展写了篇很不错的文章,他指出了许多重要的细节,比如viewport meta标签—提示iPhone如何缩放页面。他还写了高级iPhone开发的文章,罗列了更多细节(不算是真正的高级)。

我在想用ASP.NET MVC来做iPhone应用有多简单,结果表明这真是超级简单。首先,Google代码的IUI项目是用来制作iPhone基础应用的一系列Javascript和PNG组合。在Joe Hewitt工作基础上,iui团队所做的十分优秀。Joe写过一篇介绍性博文,解释了一些概念

你可以利用Safari,或者带有用户代理切换器及自定义的Firefox来模拟iPhone

比如,上图的源代码如下。注意其中包含的CSS和JS文件。

    1: <html xmlns="https://www.w3.org/1999/xhtml">
    2:  
    3: <head>
    4:  
    5: <title>iUI Prefs Demo</title>
    6:  
    7: <meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
    8:  
    9: <style type="text/css" media="screen">@import "../iui/iui.css";</style>
   10:  
   11: <script type="application/x-javascript" src="../iui/iui.js"></script>
   12:  
   13: </head>
   14:  
   15: <body>
   16:  
   17: <div class="toolbar">
   18:  
   19: <h1 id="pageTitle"></h1>
   20:  
   21: <a id="backButton" class="button" href="#"></a>
   22:  
   23: </div>
   24:  
   25: <form id="settings" title="Settings" class="panel" selected="true">
   26:  
   27: <h2>Playback</h2>
   28:  
   29: <fieldset>
   30:  
   31: <div class="row">
   32:  
   33: <label>Repeat</label>
   34:  
   35: <div class="toggle" onclick=""><span class="thumb"></span><span class="toggleOn">ON</span><span class="toggleOff">OFF</span></div>
   36:  
   37: </div>
   38:  
   39: <div class="row">
   40:  
   41: <label>Shuffle</label>
   42:  
   43: <div class="toggle" onclick="" toggled="true"><span class="thumb"></span><span class="toggleOn">ON</span><span class="toggleOff">OFF</span></div>
   44:  
   45: </div>
   46:  
   47: </fieldset>
   48:  
   49: <h2>User</h2>
   50:  
   51: <fieldset>
   52:  
   53: <div class="row">
   54:  
   55: <label>Name</label>
   56:  
   57: <input type="text" name="userName" value="johnappleseed"/>
   58:  
   59: </div>
   60:  
   61: <div class="row">
   62:  
   63: <label>Password</label>
   64:  
   65: <input type="password" name="password" value="delicious"/>
   66:  
   67: </div>
   68:  
   69: <div class="row">
   70:  
   71: <label>Confirm</label>
   72:  
   73: <input type="password" name="password" value="delicious"/>
   74:  
   75: </div>
   76:  
   77: </fieldset>
   78:  
   79: </form>
   80:  
   81: </body>
   82:  
   83: </html>

注意到那些小小的toggle开关了吗?它们在div句中class="toggle",然后点击事件的处理器就会被连动至Javascript中的代码:

    1: addEventListener("click", function(event)
    2:  
    3: {
    4:  
    5: var div = findParent(event.target, "div");
    6:  
    7: if (div && hasClass(div, "toggle"))
    8:  
    9: {
   10:  
   11: div.setAttribute("toggled", div.getAttribute("toggled") != "true");
   12:  
   13: event.preventDefault(); 
   14:  
   15: }
   16:  
   17: }, true);

基于切换状态,开关也酌情显示:

    1: .toggle {
    2:  
    3: border: 1px solid #888888;
    4:  
    5: -webkit-border-radius: 6px;
    6:  
    7: background: #FFFFFF url(toggle.png) repeat-x;
    8:  
    9: font-size: 19px;
   10:  
   11: font-weight: bold;
   12:  
   13: line-height: 30px;
   14:  
   15: }
   16:  
   17: .toggle[toggled="true"] {
   18:  
   19: border: 1px solid #143fae;
   20:  
   21: background: #194fdb url(toggleOn.png) repeat-x;
   22:  
   23: }

上面的iPhone HTML页面有多个form,明确控制div,让所有的东西比起WebForms更适合MVC。Aaron在博客中阐述了他是如何把IUI加入他的内容文件夹的,有一点麻烦的就是IUI默认HTML是从Ajax调用中返回,而不是JSON。

Aaron的视图就是之后的局部视图,为IUI的内置Ajax调用而准备,所以产品目录页看上去就像这样。注意这里的标记都是独立的。

    1: <ul id="products" title="Products">
    2: <%  foreach (Product p in ViewData.Model) { %>
    3:     <li><%= Html.ActionLink(p.ProductName, "Index", "Products", new { id = p.ProductID }) %></li>
    4: <% } %>
    5: </ul>

又酷又简单。