[资源]国外的模板素材网站

mikel阅读(658)

下面推荐这几个国外模板素材网站:(如果大家有更好希望不要吝啬,拿出来大家共同分享)

FreeCssTemplates(免费下载网页模板)   :http://www.freecsstemplates.org/ 

这个网站主要用于公开的,无需注册,而且分类清楚,页面简洁找东西很方便,但唯一的不足是东西有点少

FreeWebTemplates(免费网页模板):http://www.freewebtemplates.com/

分类很清晰,每个分类的模板我认为做的都很专业,下载就直接修改使用,而且重要这个网站常常更新最新的模板(应该可以看出这个公司的业务量不错)

TemplateMonster(模板怪物圈):http://www.templatemonster.com/

这个布局太过混乱了,但素材还不错,仅作参考

CoolHomePage(门户主页模板):http://www.coolhomepages.com/ 

DesignGalaxy:http://www.designgalaxy.net/  主要是一些模板设计爱好者聚集地方

AplusTemplates:http://www.aplustemplates.com/  

WebDesignHelper:http://www.webdesignhelper.co.uk/   

TemplateHeaven:http://www.templateheaven.com/ 

CoolTemplates:http://www.coolesttemplates.com/

[C#]从零开始学习ASP.NET MVC(一) 开天辟地入门篇

mikel阅读(674)

一.摘要

和自身水平有关, 我总喜欢写入门级别的文章.比如虽然做项目用过一个内部的MVC框架, 但是当看到ASP.NET MVC时我却还是不知道从哪里入手开始学习的好.于是我写下这篇入门级的系列文章,  将老赵(Jeffrey Zhao)的ASP.NET MVC系列视频课程学到的知识再理解和再消化, 让最笨的人也能跟着我学懂ASP.NET MVC

二.人物简介

本 文的很多资料都来自老赵 , Jeffrey Zhao. 此人相信不必我多说了吧, 高手,前辈,偶像, 对老赵的敬仰如滔滔江水连绵不绝, 如黄河泛滥一发不可收拾……(省下口水文字若干). 在我搜索有没有更简单并且系统的介绍ASP.NET MVC的资料时, 搜索到了老赵在Webcast上面的系列视频教程. 当然了高手的讲解都是比较全面的, 有时侯听了1小时, 真正理解的只有几句话.于是有了一边学习一边写此系列文章的想法.其中的知识都是从老赵的教程中学习到得.

三.Hello ASP.NET MVC

现在开始跟着我一步一步学习ASP.NET MVC.在什么都不知道之前, 还是让我们先下载一个ASP.NET MVC程序. 当看到程序运行后, 我的心才会踏实很多.

首先去ASP.NET MVC的官网看看:

http://www.asp.net/mvc/

这里我们可以下载ASP.NET MVC的安装文件.目前最新版本是RC1 (注:RC, 即Release Candidate版本, 是距离正式版最近的一个版本.一般要经历RC1,2,3后即推出正式版)

另外我们可以在CodePlex上获取源代码:

http://www.codeplex.com/aspnet

在官网上下载ASP.NET MVC安装文件, 一路回车完成安装. 启动VS2008 SP1(不是VS2008?不是SP1?作为一个专业的IT人士,水平可以菜,软件咱一定要用新的!去找个新版本吧!),点击新建,在Web中可以找到:

image

点击确定即创建了一个默认的MVC项目.同时还会创建一个测试项目. 这些我现在都不懂也不关注, 直接将Web项目中的default.aspx设置为启动页, 运行项目, 一个ASP.NET MVC的项目已经运行在我的电脑上了:

image

而且那个Home和About还能点击!虽然现在我什么都不懂, 不过看着能运行的实例, 心里就踏实多了!

四.学习MVC的概念

老赵的视频教程第一讲是"MVC模式与ASP.NET MVC框架概述".主要讲解MVC的概念.那么让我们先来学习概念.

我是如此理解MVC的:

我们现在的一个ASP.NET页面通常需要做这些事情:

1.获取一个页面需要的数据. 

2.在页面的Page_Load(页面加载)方法中为我们的页面控件绑定数据

3.浏览器显示页面

MVC即Model, View, Controller

Model就是我们1中获取的网页需要的数据

Controller就是我们获取数据,然后将数据绑定到页面控件的这个业务流程.不十分正确但是可以先这样理解: Controller就是我们的Page_Load方法逻辑.

View就是我们的aspx页面,注意这是一个不包含后台代码文件的aspx页面.(其实带有.asp.cs文件也不会有编译错误,但是这样写代码就违背了MVC的设计初衷)

下面这张图很好的概括了MVC的作用:

image

一 个URL请求, ASP.NET MVC引擎会分析这个URL要使用那个Controller, 这个Controller(实际上真正的方法是Controller的Action)从数据库或者其他数据源获取数据,通常这些数据是一个业务的模型类 (即MVC中的Model). Controller将Model对象传递给页面(即MVC中的View),  页面显示在浏览器上.(这一步是ViewEngine的功能, 我们一般的ASPX页面使用的是WebForm的ViewEngine,当然也可以替换.)

五.学习实例首页

简单的概念也有了.实例也能运行了.现在就是看看这个实例是如何使用ASP.NET MVC的.从首页下手.

1.寻找入口方法

首 页网站的地址应该是 http://localhost:1847/home/index , 为什么地址不是具体的页面但是最后却将请求提交给了view/home/Index.aspx 页面? 很明显是使用了URL重写. ASP.NET中叫做UrlRouting,对应的程序集是System.Web.Routing, 打开项目的Global.asax.cs文件, 会找到我们建立的页面重写规则:

        public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",                                              // Route name
"{controller}/{action}/{id}",                           // URL with parameters
new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
);
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}

 

 

关于Routing的深入了解将在以后介绍, 这里我们完全可以照葫芦画瓢, 按照实例添加新的重写规则.

最后, http://localhost:1847/home/index 就被解析为:

Controller为Home, Action为Index, 没有id参数.

2.寻找Controller

在Controllers文件夹下我们可以找到HomeController.cs, 这里使用了一个约定, 就是如果URL中获取到的Controller名字是Home, 则他的Controller类名就是HomeController. 在URL中的名字后加上”Controller”.

实例中Controller都放在Controllers文件夹, 所以我们可以按照命名约定很容易就可以找到HomeController类

3.寻扎Action

打开HomeControllers.cs, 发现里面有两个方法:

        public ActionResult Index()
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View();
}
public ActionResult About()
{
return View();
}

其中的Index和About都是Action.这个Action是个什么东东呢?目前我只知道一个Controller可以包含多个Action, MVC模式中Controller角色的具体实现逻辑都是在Action中的.

因为我们的Action是Index, 所以自然就要调用Index()方法.这里将"Webcome to ASP.NET MVC!", 这里的Model角色就是这句话, 也就是一个字符串对象.

Controller的一个重要作用就是将Model对象传递给View,也就是具体的页面. 传递的方法就是将这个字符串放到ViewData这个集合对象中, 然后在页面上也调用这个对象获取数据. 这个ViewData 对象一定是静态的, 或者至少是和HttpContext对象关联的, 否则到了View页面上是不能够调用的.但是也不知道ASP.NET MVC是在什么时候创建了这个对象.有心深入的一会去源代码里找找就能找到答案了.

4.寻找View

Model有了,数据有了, 接下来要跳转到View去显示数据了.第一个问题就是如何从Controller中跳到View上? return View() 这句话实现了此功能.其实如果这样写大家会更清楚:

        public ActionResult Index()
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View("index");
}

View方法中可以带一个名字, 这个名字就是View的名字.如果把index改成about,那么访问/home/index就会跳转到about页!

虽然知道了我们要返回到名称是"index"的View上, 但是这个View的页面在哪里呢?在Web中有一个Views文件夹:

image

这里面存放的都是View对象, 也就是只有显示功能的aspx页面文件.但是aspx文件要遵循约定: Views下面要按照Controller创建文件夹, 比如HomeController就对应Home文件夹, 然后在里面添加view, 比如index.aspx, 那么在HomeController中返回到名为Index的View对象实际就会返回Views/Home/Index.aspx页面.

如果不写View的名字, 则认为Action的名称就是View的名称.

5.页面展示

最后的工作就是View页面使用Model数据完整页面显示工作, 在index.aspx这个没有后台代码的View对象中, 通过ViewData对象获取Model:

<%= Html.Encode(ViewData["Message"]) %>

 

接下来ViewEngine即页面引擎会将aspx中的HTML部分以及上面的数据部分和在一起返回给浏览器.

关于View对象我注意到此页面是继承自System.Web.Mvc.ViewPage而不是直接继承自System.Web.UI.Page, 而这个ViewData对象就是ViewPage中的一个属性. 这里的ViewData一定是页面级别的,当页面编译完毕这个对象就会被注销(HTTP是无状态的协议,每次请求其实都是生成一个新的ViewPage对 象).

六.总结

虽然仅仅是第一篇入门文章, 但是是不是觉得已经会用ASP.NET MVC了? 虽然学习不可以骄傲, 但是可以自豪的是ASP.NET MVC我已经不再陌生, 即使不能驾轻就熟, 偶尔说出来几个概念,给你解释解释啥是MVC, 还是很能吓唬人的. 这篇文章相当于老赵前两篇视频的知识. 本着每日一篇的原则, 我将会继续学习老赵的系列教程,  将自己的理解贡献出来. 不求最深, 但求易懂.

[C#]从零开始学习ASP.NET MVC(二) 识别URL的Routing组件

mikel阅读(773)

一.摘要

本篇文章从基础到深入的介绍ASP.NET MVC中的Routing组件. Routing翻译过来是"路由选择", 负责ASP.NET MVC的第一个工作:识别URL, 将一个Url请求"路由"给Controller. 由于今天下午参加了博客园北京俱乐部的聚会, 所以本篇文章的完工时间晚了点, 还好也是在今天发表, 总算兑现了"每日一篇"的承诺. 不久丁学就会发布北京博客园聚会活动的资料了, 我在这里先预告了!

二.承上启下

第一篇文章中我们已经学会了如何使 用ASP.NET MVC, 虽然其中还有很多的细节没有深入了解, 但是对基本的处理流程已经有了认识:来了一个Url请求, 从中找到Controller和Action的值, 将请求传递给Controller处理. Controller获取Model数据对象, 并且将Model传递给View, 最后View负责呈现页面.

而Routing的作用就是负责分析Url, 从Url中识别参数, 如图:

image

这一讲就让我们细致的了解System.Web.Routing及其相关的扩展知识.

三.Routing的作用

第一讲中实例的首页地址是: localhost/home/index

我们发现访问上面的地址, 最后会传递给 HomeController中名为index的action(即HomeController类中的index方法).

当然服务器端不会自己去实现这个功能,  关键点就是在Global.asax.cs文件中的下列代码:

        public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",                                              // Route name
"{controller}/{action}/{id}",                           // URL with parameters
new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
);
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}

 

回来看我们的Url: localhost/home/index

localhost是域名, 所以首先要去掉域名部分: home/index

对应了上面代码中的这种URL结构: {controller}/{action}/{id}

因为我们建立了这种Url结构的识别规则, 所以能够识别出 Controller是home, action是index, id没有则为默认值"".

这就是Routing的第一个作用:

1.从Url中识别出数据.比如controller,action和各种参数.

如果跟踪程序, 接下来我们会跳转到HomeController中的Index()方法.  这是Routing内部为实现的第二个作用:

2.根据识别出来的数据, 将请求传递给Controller和Action.

但从实例中我们并不知道Routing如何做的这部份工作.第五部分我做了深入讲解.

四.Routing的使用

在分析Routing的实现原理前, 先学习如何使用Routing为ASP.NET MVC程序添加路由规则.

1. 使用MapRoute()方法.

这是最简单的为ASP.NET MVC添加识别规则的方法.此方法有如下重载:

MapRoute( string name, string url);
MapRoute( string name, string url, object defaults);
MapRoute( string name, string url, string[] namespaces);
MapRoute( string name, string url, object defaults, object constraints);
MapRoute( string name, string url, object defaults, string[] namespaces);
MapRoute( string name, string url, object defaults, object constraints, string[] namespaces);
 

name参数:

规则名称, 可以随意起名.当时不可以重名,否则会发生错误:
路由集合中已经存在名为“Default”的路由。路由名必须是唯一的。

url参数:

url获取数据的规则, 这里不是正则表达式,  将要识别的参数括起来即可, 比如: {controller}/{action}

最少只需要传递name和url参数就可以建立一条Routing(路由)规则.比如实例中的规则完全可以改为:

            routes.MapRoute(
"Default",
"{controller}/{action}");

defaults参数:

url参数的默认值.如果一个url只有controller: localhost/home/

而且我们只建立了一条url获取数据规则: {controller}/{action}

那么这时就会为action参数设置defaults参数中规定的默认值. defaults参数是Object类型,所以可以传递一个匿名类型来初始化默认值:

new { controller = "Home", action = "Index" }

实例中使用的是三个参数的MapRoute方法:

            routes.MapRoute(
"Default",                                              // Route name
"{controller}/{action}/{id}",                           // URL with parameters
new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
);

constraints参数:

用来限定每个参数的规则或Http请求的类型.constraints属性是一个RouteValueDictionary对象,也就是一个字典表, 但是这个字典表的值可以有两种:

  • 用于定义正则表达式的字符串。正则表达式不区分大小写。

  • 一个用于实现 IRouteConstraint 接口且包含 Match 方法的对象。

  • 通过使用正则表达式可以规定参数格式,比如controller参数只能为4位数字:

    new { controller = @"\d{4}"}
     

    通过第IRouteConstraint 接口目前可以限制请求的类型.因为System.Web.Routing中提供了HttpMethodConstraint类, 这个类实现了IRouteConstraint 接口. 我们可以通过为RouteValueDictionary字典对象添加键为"httpMethod", 值为一个HttpMethodConstraint对象来为路由规则添加HTTP 谓词的限制, 比如限制一条路由规则只能处理GET请求:

    httpMethod =  new HttpMethodConstraint(  "GET", "POST"  )
    

    完整的代码如下:

                routes.MapRoute(
    "Default",                                              // Route name
    "{controller}/{action}/{id}",                           // URL with parameters
    new { controller = "Home", action = "Index", id = "" },  // Parameter defaults
    new { controller = @"\d{4}" , httpMethod = new HttpMethodConstraint( "GET", "POST" ) }
    );

    当然我们也可以在外部先创建一个RouteValueDictionary对象在作为MapRoute的参数传入, 这只是语法问题.

    namespaces参数:

    此参数对应Route.DataTokens属性. 官方的解释是:

    获取或设置传递到路由处理程序但未用于确定该路由是否匹配 URL 模式的自定义值。

    我目前不知道如何使用. 请高手指点

    2.MapRoute方法实例

    下面通过实例来应用MapRoute方法. 对于一个网站,为了SEO友好,一个网址的URL层次不要超过三层:

    localhost/{频道}/{具体网页}

    其中域名第一层, 频道第二层, 那么最后的网页就只剩下最后一层了. 如果使用默认实例中的"{controller}/{action}/{其他参数}"的形式会影响网站SEO.

    假设我们的网站结构如下:

    image

    下面以酒店频道为例, 是我创建的Routing规则:

            public static void RegisterRoutes(RouteCollection routes)
    {
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    #region 酒店频道部分
    // hotels/list-beijing-100,200-3
    routes.MapRoute(
    "酒店列表页",
    "hotels/{action}-{city}-{price}-{star}",
    new { controller = "Hotel", action = "list", city = "beijing", price="-1,-1", star="-1" },
    new { city=@"[a-zA-Z]*",price=@"(\d)+\,(\d)+", star="[-1-5]"}
    );
    //hotels/所有匹配
    routes.MapRoute(
    "酒店首页",
    "hotels/{*values}",
    new { controller = "Hotel", action = "default", hotelid = "" }
    );
    #endregion
    //网站首页.
    routes.MapRoute(
    "网站首页",
    "{*values}",
    new { controller = "Home", action = "index"}
    );
    }
     

    实现的功能:

    (1)访问 localhost/hotels/list-beijing-100,200-3 会访问酒店频道的列表页,并传入查询参数

    (2)访问 localhost/hotels 下面的任何其他页面地址, 都会跳转到酒店首页.

    (3)访问 localhost 下面的任何地址, 如果未匹配上面2条, 则跳转到首页.

    简单总结:

    (1)Routing规则有顺序(按照添加是的顺序), 如果一个url匹配了多个Routing规则, 则按照第一个匹配的Routing规则执行.

    (2)由于上面的规则, 要将具体频道的具体页面放在最上方, 将频道首页 和 网站首页 放在最下方.

    (3) {*values} 表示后面可以使任意的格式.

    3.使用Route类

    MapRoute方法虽然简单, 但是他是本质也是通过创建Route类的实例, 为RouteCollection集合添加成员.

    下载最新版本的MSDN-Visual Studio 20008 SP1, 已经可以找到Route类的说明.

    创建一个Route类实例,最关键的是为以下几个属性赋值:

    属性名称 说明 举例
    Constraints 获取或设置为 URL 参数指定有效值的表达式的词典。 {controller}/{action}/{id}
    DataTokens 获取或设置传递到路由处理程序但未用于确定该路由是否匹配 URL 模式的自定义值。 new RouteValueDictionary { { "format", "short" } }
    Defaults 获取或设置要在 URL 不包含所有参数时使用的值。 new { controller = "Home", action = "Index", id = "" }
    RouteHandler 获取或设置处理路由请求的对象。 new MvcRouteHandler()
    Url 获取或设置路由的 URL 模式。 new { controller = @"[^\.]*" }

    这些属性除了RouteHandler以外, 其他的都对应MapRoute方法的参数.RouteHandler是实现了IRouteHandler接口的对象.关于此接口的作用在第五部分Routing深入解析中做讲解.

    五.Routing深入解析

    对于一个一般开发人员来说, 上面的知识已经完全足够你使用ASP.NET MVC时使用Routing了.

    接下来的部分我将深入Routing的机制讲解Routing的高级应用.但是因为是"高级应用", 加上这篇文章已经太长了, 再加上马上今天就过去了, "每日一篇"的承诺一定要兑现的, 所以不会对所有细节进行讲解. 或者也可以略过此部分.

    Routing如何将请求传递给Controller?上面讲解Routing作用的时候, 我们就分析出Routing会将请求传递给Controller, 但是Routing如何做的这部份工作我们却看不到.关键在于MapRoute()这个方法封装了具体的细节.

    虽然MapRoute方法是RouteCollection对象的方法,但是却被放置在System.Web.Mvc程序集中, 如果你的程序只引用了System.Web.Routing, 那么RouteCollection对象是不会有MapRoute方法的. 但是如果你同又引用了System.Web.Mvc, 则在mvc的dll中为RouteCollection对象添加了扩展方法:

           public static void IgnoreRoute(this RouteCollection routes, string url);
    public static void IgnoreRoute(this RouteCollection routes, string url, object constraints);
    public static Route MapRoute(this RouteCollection routes, string name, string url);
    public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults);
    public static Route MapRoute(this RouteCollection routes, string name, string url, string[] namespaces);
    public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints);
    public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, string[] namespaces);
    public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces);

    RouteCollection是一个集合,他的每一项应该是一个Route对象. 但是我们使用MapRoute时并没有创建这个对象, 这是因为当我们将MapRoute方法需要的参数传入时, 在方法内部会根据参数创建一个Route对象:

            public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) {
    if (routes == null) {
    throw new ArgumentNullException("routes");
    }
    if (url == null) {
    throw new ArgumentNullException("url");
    }
    Route route = new Route(url, new MvcRouteHandler()) {
    Defaults = new RouteValueDictionary(defaults),
    Constraints = new RouteValueDictionary(constraints)
    };
    if ((namespaces != null) && (namespaces.Length > 0)) {
    route.DataTokens = new RouteValueDictionary();
    route.DataTokens["Namespaces"] = namespaces;
    }
    routes.Add(name, route);
    return route;
    }

    上面就是MapRoute方法的实现, 至于在创建Route对象时第二个参数是一个MvcRouteHandler, 它是一个实现了IRouteHandler接口的类. IRouteHandler十分简单只有一个方法:

    IHttpHandler GetHttpHandler(RequestContext requestContext);

    参数是一个RequestContext 类实例, 这个类的结构也很简单:

        public class RequestContext
    {
    public RequestContext(HttpContextBase httpContext, RouteData routeData);
    public HttpContextBase HttpContext { get; }
    public RouteData RouteData { get; }
    }

    其中的一个属性RouteData就包含了Routing根据Url识别出来各种参数的值, 其中就有Controller和Action的值.

    归根结底, ASP.NET MVC最后还是使用HttpHandler处理请求. ASP.NET MVC定义了自己的实现了IHttpHandler接口的Handler:MvcHandler,  因为MvcRouteHandler的GetHttpHandler方法最后返回的就是MvcHandler. 

    MvcHandler的构造函数需要传入RequestContext 对象, 也就是传入了所有的所有需要的数据, 所以最后可以找到对应的Controller和Action, 已经各种参数.

    六.测试Routing

    因为一个Url会匹配多个routing规则, 最后常常会遇到规则写错或者顺序不对的问题.于是我们希望能够看到Url匹配Routing的结果.

    其中最简单的办法就是使用RouteDebug辅助类. 这个类需要单独下载dll组件, 我将此组件的下载放在了博客园上:

    http://files.cnblogs.com/zhangziqiu/RouteDebug-Binary.zip

    解压缩后是一个DLL文件, 将这个DLL文件添加到项目中并且添加引用.

    使用方法很简单, 只需要在Application_Start方法中添加一句话:

    RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);

    比如下面是我的示例中的代码:

            protected void Application_Start()
    {
    RegisterRoutes(RouteTable.Routes);
    RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);
    }

    现在你访问任何URL, 都会出现RouteDebug页面, 如下:

    image

    其中不仅有你的所有Routing规则, 还显示了是否匹配.并且按照顺序列出. 还有识别的参数列表.

    当你不想测试Routing规则的时候则注释掉这一段, 即可回复跳转到View对象上.

    七.总结

    本文讲解了ASP.NET MVC中一个关键的组件:Routing的使用. System.Web.Routing在Framework3.5 SP1中已经集成, 也就是说虽然我们还没有ASP.NET MVC的正式版, 但是Routing组件却已经提早发布了. 因为Routing是一个相对独立的组件, 不仅能和ASP.NET MVC配额使用, 也可以用于任何需要URL路由的项目. 另外Routing的作用和Url重写(Url Rewrite)是有区别的, 你会发现Routing和Url Rewrite相比其实很麻烦, 无论是添加规则还是传递参数.对UrlRewite感兴趣的可以去寻找UrlRewrite.dll这个组件, 很简单很强大, 有关两者的异同以及如何使用UrlRewrite这里不在多说了.

    另外今天博客园北京俱乐部聚会, 听了2位大师的讲座, 见到了至今没记住名字和样子的同行们, 很是激动和兴奋. 期待俱乐部领导将活动照片和资料放出!

    本文的示例下载地址:

    http://files.cnblogs.com/zhangziqiu/Demo-2.rar

    [Flex]AsWing:Java开发者的ActionScript朋友?

    mikel阅读(1070)

    作者 Moxie Zhang译者 张龙 发布于 2009年3月1日 上午8时38分

    社区
    Java
    主题
    RIA
    标签
    ActionScript

    长久以来Java Swing一直是Java开发者主要的图形界面构建包,那么Java Swing的经验和技巧能否用于构建基于ActionScript 3的RIA系统呢?AsWing Framework的目标就在于此。InfoQ有幸采访了AsWing的首席开发者iiley Chen以了解AsWing是如何有助于RIA开发的。

    在被问到为何创建AsWing而不是使用其他的UI框架时,iiley Chen说到:

    确实,Flex出现之前有很多很酷的框架,但大多数都不易使用并且功能不完全。很多框架都缺少一些重要的组件,如Tree、 DataGrid及强大的布局管理器等等。在2005年开发第一个大型应用(一个Flash做的在线社区)时,我需要一个强大的UI框架。我有Java Swing的经验并且喜欢Swing的架构和设计模式。但我坚信如果有一个类似于Swing的Flash UI框架的话,我可以快速且舒服的构建出应用的UI。因此我开始用ActionScript2语言开发AsWing并保持其大部分API与Swing一 致。现在AsWing已经基于ActionScript3了并且重新进行了设计,同时还多次进行了重构。一些家伙甚至告诉我它比Swing和Flex还要 好用。谢谢他们,他们让我觉得开发AsWing是件有意义的事。

    关于AsWing的主要优势和特点,Chen说到:

    主要优势在于你可以使用纯ActionScript编码轻松构建流式/动态的UI。AsWing的核心仅仅是一些易于操纵和管理的ActionScript类。如果你具有Java Swing经验,那么这些技巧也可以用到AsWing上。
    AsWing提供了40多个现代的UI组件,包括专业的ColorMixiers和一些特别的组件,如JLabelButton、Form、Folder及GridList。
    此外,凭借设计良好的MVC模式,你可以轻松将数据更新到UI视图上。就像Flex拥有数据绑定一样,AsWing也有各种数据模型,他们会自动通知视图进行更新。
    其中的SkinBuilder工具可以帮助开发者创建完全不同的皮肤,所用的方式仅仅是提供一些组件图片或是Flash符号。除此之外,GuiBuilder有助于UI的布局设计并生成ActionScript源代码。
    最后,AsWing不是重量级的。并不像其他的UI框架(他们也是应用框架),AsWing只关注于UI。你可以将AsWing与任何其他的应用框架组合起来使用。

    就开发环境来说,AsWing非常灵活。Chen说到:

    AsWing的开发没有什么特别之处。任何ActionScript开发环境都可以,比如说Flex Builder、FDT及FlashDevelop等等。AsWing仅仅是个项目中可以使用的ActionScript库。你可以使用Flex编译器或 是Flash编译器来编译AsWing应用。其中的GuiBuilder工具是个AIR应用,因此需要AIR运行时才能运行它。

    就AsWing的路线图,Chen说到:

    目前我正忙于AsWing2.0,这是个主版本。我们将用更好的方式重新设计其感官样式。最重要的新特性就是新的皮肤技术的引 入。你只需就倾斜度、色调、圆角或阴影属性编写几行代码就可以改变组件样式而无需开发复杂的ComponentUI类。同时我们还会增加一些新组件,如 Numeric Stepper、Date Chooser、Advanced TextArea及Advanced Table等等。

    Chen给出了如下的Hello World AsWing应用代码:

    package{
    import flash.display.Sprite;
    import org.aswing.*;
    public class HelloWorld extends Sprite{
        public function HelloWorld(){
            AsWingManager.initAsStandard(this);
            JOptionPane.showMessageDialog("Title", "Hello World!");

        }
    }
    }

    Java Swing开发者对此是不是很熟悉呢?

    查看英文原文:AsWing, An ActionScript Fiend of Java Developers?

    [Flex]FMS系列(一):第一个FMS程序,连接到FMS服务器(Flash/Flex两种实现)

    mikel阅读(624)

    FMS是个很牛X的东西,到底有多牛X我不想在这里多说,有兴趣的朋友可以baidu一把了解一下,如果实在是不想动手,那你就点下面的连接吧,我搜索了点资料简单的总结了一下。

        你可以点击这里了解一些关于FMS的基本知识: 了解一些FMS的基本概念

         通常做FMS都是和Flash或是Flex结合开发的,特别是在视频流这方面相当的突出,成功案例也不少,比如http://www.tudou.com,  www.ku6.com , http://www.15dv.com 等视频网站都与FMS挂钩。本人也是因为工作需要,趁工作之余来学习这门技术,想通过写博客的方式来巩固和分享学习,更希望爱好或是在从事这方面开发工作 的朋友多多指正,交流。OK,本文就以连接FMS服务器作为写作话题,来看看我们学习FMS应该从什么地方出发,逐步的走上更高的台阶。

         Adobe公司的产品Flash和Flex都可以结合FMS进行编程,本文示例比较简单,为了多凑几个字我打算通过Flash和Flex两种实现来介绍怎么来实现我们的第一个FMS程序“连接到FMS服务器”。

         上山砍柴不忘磨柴刀,那么我们做技术开发肯定也离不开对开发环境,开发工具,开发语言的选择和准备。本文中我们的工具就是Flash CS 4,Flex Builder 3和FMS 3.0,所使用的开发语言是ActionScript 3.0,这里我不想浪费时间去介绍软件的安装,相信看这篇文章的你对于安装软件不会存在有什么难度,OK,下面看看怎么编码实现。

    一 、FMS应该做些什么 

         本文中所使用到的FMS是非常简单的,主要就就是建立一个FMS应用,方法很简单。找到你安装FMS的目录你会发现里面有一个 appliations的目录。对的,它就是管理FMS应用的目录,进入该目录在里面建立一个文件夹就OK,我建立的文件夹为"firstFMS"。

     

    二、Flash连接到FMS服务器

         首先建立一个Flash文件(ActionScript 3.0)并将其保存在某个目录(自己决定吧)中。然后打开组件面板(可以按Ctrl+F7)从组件面板中拖拽一个button组件到刚建立好的Flash 的舞台(也就是Flash显示东西的那一块地方),然后通过属性面板(可以按Ctrl+F3)将刚拖拽出的button取个名字(Flash中叫他为实例 名,舞台中的每一个组件就是一相对应的对象的实例),我取的是btnConnFMS

         完成上面两步后回到舞台,鼠标在舞台中空白位置点击一下,然后同样打开属性面板,你会发现现在的属性面板和先前的有些不一样,在发布选项下找到“类”,这里我填写的为“ConnFMS”,表示我将要通过ConnFMS.as这个类文件来对当前的这个Flash进行编码。

         上面承诺了由ConnFMS.as来负责Flash的编码工作,那该怎么做呢?建立一个ActionScript类文件,保存在之前保存Flash文件的同一目录就OK,记住这个类文件一定是“ConnFMS.as”。下面是ConnFMS.as的完整代码:

     1 package
     2 {
     3     import flash.net.NetConnection;
     4     import flash.net.NetStream;
     5     import flash.display.MovieClip;
     6     import flash.net.Responder;
     7     import flash.events.MouseEvent;
     8     import flash.events.NetStatusEvent;
     9     import flash.events.AsyncErrorEvent;
    10     
    11     public class ConnFMS extends MovieClip
    12     {
    13         private var nc:NetConnection;
    14         
    15         public function ConnFMS()
    16         {
    17             btnConnFMS.label="连接到FMS";
    18         }
    19         
    20         private function onClickHandler(evt:MouseEvent):void
    21         {
    22             trace("正在连接FMS服务器");
    23             nc = new NetConnection();
    24             nc.connect("rtmp://localhost/firstFMS");
    25             nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatusHandler);
    26         }
    27         
    28         private function onNetStatusHandler(evt:NetStatusEvent):void
    29         {
    30             switch (evt.info.code)
    31             {
    32                 case "NetConnection.Connect.Success":
    33                     trace("成功连接FMS服务器!");
    34                     break;
    35                 case "NetConnection.Connect.Rejected":
    36                     trace ("访问FMS服务器权限不足,连接被拒绝!");
    37                     break;
    38                 case "NetConnection.Connect.InvalidApp":
    39                     trace("指定的应用程序名称没有找到");
    40                     break;
    41                 case "NetConnection.Connect.Failed":
    42                     trace("连接失败!");
    43                     break;
    44                 case "NetConnection.Connect.AppShutDown":
    45                     trace("服务器端应用程序已经关闭(由于资源耗用过大等原因)或者服务器已经关闭!");
    46                     break;
    47                 case "NetConnection.Connect.Closed":
    48                     trace("与FMS的连接中断!");
    49                     break;
    50             }
    51         }
    52     }
    53 }

     

     三、Flex连接到FMS服务器

         首先建立好Flex项目,默认会创建一个MXML文件,简单化实现这里就直接在这个MXML文件里来实现连接FMS。代码上和Flash连接到FMS几乎没有什么差别,主要就是学习NetConnection类来完成,如下代码定义:

    1 //Flex与FMS建立连接的对象
    2 private var netConn:NetConnection;
    3 //FMS服务器的地址,使用rtmp协议
    4 private var rtmpUrl:String="rtmp://localhost/firstFMS"; 

     

       NetConnection指示 Flash Player 是通过持久性的 RTMP 连接连接到服务器,实现这一步操作是通过NetConnection类的connect()方法来完成的。如下:

    1 //当Flex应用程序启动的时候就建立与FMS服务器的连接
    2 internal function onInit():void
    3 {
    4     netConn = new NetConnection();
    5     netConn.connect(rtmpUrl);
    6     netConn.addEventListener(NetStatusEvent.NET_STATUS,onNetStatusHandler);
    7     netConn.addEventListener(AsyncErrorEvent.ASYNC_ERROR,onAsyncErrorHandler);
    8 }   

     

      connect()方法打开指定rtmp协议地址的FMS服务器的连接。一旦调用该方法NetConnection的对象就会捕捉到FMS返回的一个网络连接状态,通过NetStatusEvent事件监听可以得到返回状态的值(详细见本文前Flash部分),AsyncErrorEvent事件为异步引发异常(既本机异步代码)时调度。关于NetConnection的各种状态的详细请查看本文之前的Flash实例有详细的介绍。

       由于实例比较简单,这里我就不在多说废话,下面是通过Flex实现连接到FMS的完整代码:

     1<?xml version="1.0" encoding="utf-8"?>
     2<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
     3    <mx:Script>
     4        <![CDATA[
     5            import mx.controls.Alert;
     6            //Flex与FMS建立连接的对象
     7            private var nc:NetConnection;
     8            //FMS服务器的地址,使用rtmp协议
     9            private var rtmpUrl:String="rtmp://localhost/firstFMS";
    10            
    11            //当Flex应用程序启动的时候就建立与FMS服务器的连接
    12            internal function onClick():void
    13            {
    14                nc = new NetConnection();
    15                nc.connect(rtmpUrl);
    16                nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatusHandler);
    17                nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR,onAsyncErrorHandler);
    18            }

    19            
    20            private function onClickHandler(evt:MouseEvent):void
    21            {
    22                trace("正在连接FMS服务器");
    23                nc = new NetConnection();
    24                nc.connect("rtmp://localhost/firstFMS");
    25                nc.client=this;
    26                nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatusHandler);
    27                nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR,onAsyncErrorHandler);
    28            }

    29        
    30            private function onNetStatusHandler(evt:NetStatusEvent):void
    31            {
    32                switch (evt.info.code)
    33                {
    34                    case "NetConnection.Connect.Success":
    35                        trace("成功连接FMS服务器!");
    36                        break;
    37                    case "NetConnection.Connect.Rejected":
    38                        trace ("访问FMS服务器权限不足,连接被拒绝!");
    39                        break;
    40                    case "NetConnection.Connect.InvalidApp":
    41                        trace("指定的应用程序名称没有找到");
    42                        break;
    43                    case "NetConnection.Connect.Failed":
    44                        trace("连接失败!");
    45                        break;
    46                    case "NetConnection.Connect.AppShutDown":
    47                        trace("服务器端应用程序已经关闭(由于资源耗用过大等原因)或者服务器已经关闭!");
    48                        break;
    49                    case "NetConnection.Connect.Closed":
    50                        trace("与FMS的连接中断!");
    51                        break;
    52                }

    53            }

    54            
    55            private function onAsyncErrorHandler(evt:AsyncErrorEvent):void
    56            {}
    57    ]]>
    58    </mx:Script>
    59    <mx:Button x="135" y="89" label="Button" click="onClick()" fontSize="12" fontWeight="normal"/>
    60</mx:Application>

     

       

    四、注意事项

      通常新手在学习FMS的时候都会遇到一个问题,那就是通过NetConnection连接FMS服务器的时候,连接状态总是返回 “NetConnection.Connect.Rejected”这样的状态结果,然后接着还有会有一个 “NetConnection.Connect.Failed”状态,是什么原因造成这样的错误的呢?

      第一个错误从本文实例中你可以得到,是访问FMS服务器的权限问题,如果FMS没有开设足够的访问权限,通常在访问FMS的客户端都会接受到这 样一个异常状态。第二个错误又是怎么产生的呢?这还是又访问权限引起,当客户端没有主够的权限访问FMS服务器,就将返回 “NetConnection.Connect.Rejected”状态并自动断开与FMS服务器的连 接,“NetConnection.Connect.Failed”状态本身是由于连接服务器失败产生,而这里是因为权限问题而引发的。

      前几天很多朋友就在问我这个问题,怎么来解决这个问题呢?如果你是一个技术专研者,如果又你赶兴趣的技术在你面前,你首先会做什么?查看官方提 供的文档?实例代码?还是什么? OK,其实要解决这个问题很简单,在FMS服务器安装好后的目录下有一个"applications"目录,里面有两个FMS默认安装的FMS服务器 (live和vod),随便打开一个默认安装然后打开里面的"readme.txt"文件会看到下面的字样:

    ================================================================
    Deploying an unsigned vod service
    ================================================================
        
    1. Create a new folder in the {FMS-Install-Dir}/applications folder.
    2. If you are replacing the default Adobe signed live service, back up
       the following files:
       * main.far
       * Application.xml
       * allowedHTMLDomains.txt
       * allowedSWFDomains.txt

    3. Copy files from {FMS-Install-Dir}/samples/applications/vod to the directory you created in step 1.

     

      现在你知道怎么解决上面出现的问题了吗??将这main.far、Application.xml、 allowedHTMLDomains.txt和allowedSWFDomains.txt这四个文件复制到你创建的FMS服务器目录下就解决了,运行 上面的实例程序,然后可以通过FMS的管理控制台查看到详细的连接信息。

      我通常是使用的FMS安装目录下的fms_adminConsole.swf 来查看连接信息,也可以使用FMSfms_adminConsole.htm查看。

    [C#]C#的Enum——枚举

    mikel阅读(919)

    枚举

      枚举类型声明为一组相关的符号常数定义了一个类型名称。枚举用于“多项选择”场合,就是程序运行时从编译时已经设定的固定数目的“选择”中做出决定。

      枚举类型(也称为枚举)为定义一组可以赋给变量的命名整数常量提供了一种有效的方法。例如,假设您必须定义一个变量,该变量的值表示一周中的一天。该变量只能存储七个有意义的值。若要定义这些值,可以使用枚举类型。枚举类型是使用 enum 关键字声明的。 

    enum Days { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday };

      默认情况下,枚举中每个元素的基础类型是 int。可以使用冒号指定另一种整数值类型。
      如果不为枚举数列表中的元素指定 值,则它们的值将以 1 为增量自动递增。在前面的示例中,Days.Sunday 的值为 0,Days.Monday 的值为 1,依此类推。创建新的 Days 对象时,如果不显式为其赋值,则它将具有默认值 Days.Sunday (0)。创建枚举时,应选择最合理的默认值并赋给它一个零值。这便使得只要在创建枚举时未为其显式赋值,则所创建的全部枚举都将具有该默认值。枚举中大小 写敏感,但是建议不要这样。

    枚举的优点:
      <1>枚举可以使代码更易于维护,有助于确保给变量指定合法的、期望的值。
      <2>枚举使代码更清晰,允许用描述性的名称表示整数值,而不是用含义模糊的数来表示。
      <3>枚举使代码更易于键入。在给枚举类型的实例赋值时,VS.NET IDE会通过IntelliSense弹出一个包含可接受值的列表框,减少了按键次数,并能够让我们回忆起可能的值

    枚举实例

      声明: 

    public enum TimeOfDay
    {
        Moning 
    = 0,
        Afternoon 
    = 1,
        Evening 
    = 2,
    };

      使用: 

        public string getTimeOfDay(TimeOfDay time)
        {
            
    string result = string.Empty;
            
    switch (time)
            {
                
    case TimeOfDay.Moning:
                    result 
    = "上午";
                    
    break;
                
    case TimeOfDay.Afternoon:
                    result 
    = "下午";
                    
    break;
                
    case TimeOfDay.Evening:
                    result 
    = "晚上";
                    
    break;
                
    default:
                    result 
    = "未知";
                    
    break;
            }
            
    return result;
        }

     

    枚举方法 

      <1>获取枚举字符串

    TimeOfDay time = TimeOfDay.Afternoon;
    Console.WriteLine(time.ToString());
    //输出:Afternoon

     

      <2>Enum.Parse()方法。这个方法带3个参数,第一个参数是要使用的枚举类型。其语法是关键字typeof后跟放在括号中的枚举类名。typeof运算符将在第5章详细论述。第二个参数是要转换的字符串,第三个参数是一个bool,指定在进行转换时是否忽略大小写。最后,注意Enum.Parse()方法实际上返回一个对象引用—— 我们需要把这个字符串显式转换为需要的枚举类型(这是一个取消装箱操作的例子)。对于上面的代码,将返回1,作为一个对象,对应于TimeOfDay.Afternoon的枚举值。在显式转换为int时,会再次生成1。

    TimeOfDay time2 = (TimeOfDay) Enum.Parse(typeof(TimeOfDay), "afternoon"true);
    Console.WriteLine((
    int)time2);//输出1

     

      <3>得到枚举的某一值对应的名称

    lbOne.Text = Enum.GetName(typeof(TimeOfDay), 0);

        <4>得到枚举的所有的值 

    foreach (int i in Enum.GetValues(typeof(TimeOfDay)))
                lbValues.Text 
    += i.ToString();

        <5>枚举所有的名称 

    foreach(string temp in Enum.GetNames(typeof(TimeOfDay)))
                lbNames.Text
    +=temp;

      

    枚举和常量

      优先考虑枚举。

      在C#中,枚举的真正强大之处是它们在后台会实例化为派生于基类System.Enum的结构。这表示可以对它们调用方法,执行有用的任务。注 意因为.NET Framework的执行方式,在语法上把枚举当做结构是不会有性能损失的。实际上,一旦代码编译好,枚举就成为基本类型,与int和float类似。

      但是在实际应用中,你也许会发现,我们经常用英语定义枚举类型,因为开发工具本来就是英文开发的,美国人用起来,就直接能够明白枚举类型的含 义。其实,我们在开发的时候就多了一步操作,需要对枚举类型进行翻译。没办法,谁让编程语言是英语写的,如果是汉语写的,那我们也就不用翻译了,用起枚举 变得很方便了。举个简单的例子,TimeOfDay.Morning一看到Morning,美国人就知道是上午,但是对于中国的使用者来说,可能有很多人 就看不懂,这就需要我们进行翻译、解释,就向上面的getTimeOfDay()的方法,其实就是做了翻译工作。所以,在使用枚举的时候,感觉到并不是很 方便,有的时候我们还是比较乐意创建常量,然后在类中,声明一个集合来容纳常量和其意义。

      使用常量定义:这种方法固然可行,但是不能保证传入的参数day就是实际限定的。

    using System;
    using System.Collections.Generic;
    public class TimesOfDay
    {
        
    public const int Morning = 0;
        
    public const int Afternoon = 1;
        
    public const int Evening = 2;
        
    public static Dictionary<intstring> list;
        
    /// <summary>
        
    /// 获得星期几
        
    /// </summary>
        
    /// <param name="day"></param>
        
    /// <returns></returns>
        public static string getTimeNameOfDay(int time)
        {
            
    if (list == null || list.Count <= 0)
            {
                list 
    = new Dictionary<intstring>();
                list.Add(Morning, 
    "上午");
                list.Add(Afternoon, 
    "下午");
                list.Add(Evening, 
    "晚上");
            }
            
    return list[time];
        }
    }

     

    希望能够找到一种比较好的方法,将枚举转为我们想要的集合。搜寻了半天终于找到了一些线索。通过反射,得到针对某一枚举类型的描述。

    枚举的定义中加入描述 

    using System;
    using System.ComponentModel;
    public enum TimeOfDay
    {
        [Description(
    "上午")]
        Moning,
        [Description(
    "下午")]
        Afternoon,
        [Description(
    "晚上")]
        Evening,
    };

     

       获得值和表述的键值对

            /// <summary>
            
    /// 从枚举类型和它的特性读出并返回一个键值对
            
    /// </summary>
            
    /// <param name="enumType">Type,该参数的格式为typeof(需要读的枚举类型)</param>
            
    /// <returns>键值对</returns>
            public static NameValueCollection GetNVCFromEnumValue(Type enumType)
            {
                NameValueCollection nvc 
    = new NameValueCollection();
                Type typeDescription 
    = typeof(DescriptionAttribute);
                System.Reflection.FieldInfo[] fields 
    = enumType.GetFields();
                
    string strText = string.Empty;
                
    string strValue = string.Empty;
                
    foreach (FieldInfo field in fields)
                {
                    
    if (field.FieldType.IsEnum)
                    {
                        strValue 
    = ((int)enumType.InvokeMember(field.Name, BindingFlags.GetField, nullnullnull)).ToString();
                        
    object[] arr = field.GetCustomAttributes(typeDescription, true);
                        
    if (arr.Length > 0)
                        {
                            DescriptionAttribute aa 
    = (DescriptionAttribute)arr[0];
                            strText 
    = aa.Description;
                        }
                        
    else
                        {
                            strText 
    = field.Name;
                        }
                        nvc.Add(strText, strValue);
                    }
                }
                
    return nvc;
            }

     

    [C#]Asp.net MVC:自定义的MVC Pager

    mikel阅读(802)

    实例懒得做。切几个图把代码发上要用的自己搞啦~

    下面是一个helper类。


    namespace System.Web.Mvc
    {
        
    public enum BarStyle
        
    {
            yahoo, digg, meneame, flickr, sabrosus, scott, quotes, black, black2, grayr, yellow, jogger, starcraft2, tres, megas512, technorati, youtube, msdn, badoo, viciao, yahoo2, green_black
        }

        
    public static class PagerBarExtension
        
    {

            
    public static string RenderPagerBar(this HtmlHelper html, int page, int total)
            
    {
                
    return RenderPagerBar(html, page, total, BarStyle.technorati);
            }


            
    public static string RenderPagerBar(this HtmlHelper html, int page, int total, BarStyle style)
            
    {
                
    return RenderPagerBar(html, page, total, style, total);
            }


            
    public static string RenderPagerBar(this HtmlHelper html, int page, int total, BarStyle style, int show)
            
    {
                
    if (total == 1)
                
    {
                    
    return "";
                }

                
    else
                
    {
                    StringBuilder sb 
    = new StringBuilder();
                    
    string _path = html.ViewContext.HttpContext.Request.Path;
                    sb.Append(
    "<div class=\"");
                    sb.Append(style.ToString());
                    sb.Append(
    "\" >");

                    
    string queryString = html.ViewContext.HttpContext.Request.QueryString.ToString();
                    
    if (queryString.IndexOf("page="< 0)
                    
    {
                        queryString 
    += "&page=" + page;
                    }

                    Regex re 
    = new Regex(@"page=\d+", RegexOptions.IgnoreCase);
                    
    string result = re.Replace(queryString, "page={0}");

                    
    if (page != 1)
                    
    {
                        sb.AppendFormat(
    "<span><a href=\"{0}\" title=\"第一页\">{1}</a></span>", _path + "?" + string.Format(result, 1), "<<");
                        sb.AppendFormat(
    "<span><a href=\"{0}\" title=\"上一页\">{1}</a></span>", _path + "?" + string.Format(result, page  1), "<");
                    }

                    
    if(page>(show+1))
                    
    {
                        sb.AppendFormat(
    "<span><a href=\"{0}\" title=\"" + (show + 1) + "页\">{1}</a></span>", _path + "?" + string.Format(result,page(show + 1)), "..");

                    }

                    
    for (int i = pageshow; i <= page+show; i++)
                    
    {
                        
    if (i == page)
                        
    {
                            sb.AppendFormat(
    "<span class=\"current\">{0}</span>", i);
                        }

                        
    else
                        
    {
                            
    if (i > 0 & i<=total)
                            
    {
                                sb.AppendFormat(
    "<span><a href=\"{0}\">{1}</a></span>", _path + "?" + string.Format(result, i), i);
                            }

                        }

                    }

                    
    if (page < (total(show)))
                    
    {
                        sb.AppendFormat(
    "<span><a href=\"{0}\" title=\"" + (show + 1) + "页\">{1}</a></span>", _path + "?" + string.Format(result, page + (show + 1)), "..");

                    }

                    
    if (page < total)
                    
    {
                        sb.AppendFormat(
    "<span><a href=\"{0}\" title=\"下一页\">{1}</a></span>", _path + "?" + string.Format(result, page + 1), ">");
                        sb.AppendFormat(
    "<span><a href=\"{0}\" title=\"最后一页\">{1}</a></span>", _path + "?" + string.Format(result, total), ">>");

                    }

                    sb.AppendFormat(
    "<span class=\"current\">共{1}页</span>", page, total);
                    sb.Append(
    "</div>");
                    
    return sb.ToString();
                }

            }

        }

    }

     

    使用(VIEW):


    <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

    <asp:Content ID="indexHead" ContentPlaceHolderID="head" runat="server">
        
    <title>Home Page</title>
        
    <link href="/Content/pagecss.css" rel="stylesheet" type="text/css" />
    </asp:Content>
        
    <asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
        
    <%= Html.ActionLink("带其它参数","Index",new {s = "MVC"} )%>
        
    <%= Html.ActionLink("带其它参数2","Index",new { cid = 3} )%>
        
    <%= Html.ActionLink("带其它参数3","Index",new {s = "MVC" , cid = 5} )%>
        
        
    <%= Html.RenderPagerBar(Convert.ToInt32(ViewData["Page"]),Convert.ToInt32(ViewData["Total"]))%>
        
    <%= Html.RenderPagerBar(Convert.ToInt32(ViewData["Page"]),Convert.ToInt32(ViewData["Total"]),BarStyle.badoo )%>
        
    <%= Html.RenderPagerBar(Convert.ToInt32(ViewData["Page"]),Convert.ToInt32(ViewData["Total"]),BarStyle.badoo,3 )%>
        
    <%= Html.RenderPagerBar(Convert.ToInt32(ViewData["Page"]),Convert.ToInt32(ViewData["Total"]),BarStyle.black,4 )%>
        
    <%= Html.RenderPagerBar(Convert.ToInt32(ViewData["Page"]),Convert.ToInt32(ViewData["Total"]),BarStyle.digg,5 )%>
        
    <%= Html.RenderPagerBar(Convert.ToInt32(ViewData["Page"]),Convert.ToInt32(ViewData["Total"]),BarStyle.flickr,3 )%>
        
    <%= Html.RenderPagerBar(Convert.ToInt32(ViewData["Page"]),Convert.ToInt32(ViewData["Total"]),BarStyle.grayr,3 )%>
        
    </asp:Content>

    最后一个int参数表示显示当前页左右各多少个页码

     效果:

     

    controller:

     


            public ActionResult Index(int? page,string s,int? cid)
            {
                int _page = page??1;
                ViewData["Message"] = "Welcome to ASP.NET MVC!";
                ViewData["Page"] = _page;
                ViewData["Total"] = 20;

                return View();
            }

     

    不是啥高深的东西,不过蛮实用,

    计算总页数和skip啥的就自己搞啦。给宝宝换尿布了

    实例下载:/Files/francis67/MvcPagerDemo.rar

    环境:VS2008SP1 ,ASP.NET MVC RC1

    [C#]Asp.Net Mvc: Implement your custom ModelBinder

    mikel阅读(808)

    环境:

    Windows 2008, VS 2008 SP1, ASP.NET Mvc RC1

    ——————————————————————————

    上文:ASP.NET Mvc: Model Binding 机制分析  中,我们简单分析了ASP.NET MVC中Model Binding的过程,非常粗糙,本文将探索如何实现一个自己的ModelBinder,并进一步展示前文忽略的若干细节。

    假设,我们现在有一个Book类,

    现在我们要实现添加Book的功能,因此,新建一个BookController,并且加入一个Action:

    建立相应的View:


    其 实,到这一步,当我们提交表单的时候,在Action里面已经可以获得Book自动绑定,这归功于内建的DefaultModelBinder。但是,我 们基于某种考虑,想要使用自己创建的ModelBinder。于是,我们接着创建一个SimpleModelBinder类,该类实现了 IModelBinder接口(自定义的ModelBinder必须实现这个接口)。
    IModelBinder只有一个方法BindModel(),这个方法接受两个参数:ControllerContext, ModelBindingContext,因此,我们在实现这个方法的时候,便需要好好利用这两个参数包含的信息。

    现在来看SimpleModelBinder的具体实现:


    上 面,我尽量避免硬编码,因为我希望这个SimpleModelBinder具有一定的通用性。此外也避免Model字段名称更改的连锁反应。这里,我们通 过bindingContext.ModelType来创建一个Model实例,通过TypeDescriptor来获取Model的Property集 合,通过bindingContext.ValueProvider来取得Request的表单信息,最后返回一个Model实例。

    这样,我们的SimpleModelBinder就创建完了。那么,如何让它开始工作呢?

    于是就引出一个问题:ASP.NET MVC如何确定当前需要应用哪个ModelBinder?

    答案是:按先后顺序:(1)Action方法中Model的参数的Attribute,(2) ModelBinders.Binders字典,(3) Model类的Attribute,(4) DefaultModelBinder

    也就是说,我们有(1)(2)(3)三种方法来告诉ASP.NET MVC当前我们期望应用哪个ModelBinder到哪个Model。

    (1) 在Action的Model参数上加Attribute:


    (2) 将SimpleModelBinder添加到ModelBinders.Binders字典中:


    (3) 在Book类定义时加上Attribute:


    好啦,三个方法任由你选择。

    这里,我们创建了一个很简单的自定义的ModelBinder,但你是否知道它至少还缺失了一个很重要的功能,就是绑定时对Model的 Property的过滤,因为一直以来我都把BindAttribute这个成员给忽视了。下篇,我们就来谈谈BindAttribute,并对 SimpleModelBinder做稍稍的完善。

    此外,DefaultModelBinder很强大了,什么时候需要应用自定义的ModelBinder,则需要在实际项目中慢慢琢磨。 

    Copyright

    作者: Tristan G
    本文版权归作者和博客园共有,欢迎转载 🙂

    [Erlang]进入Erlang的世界

    mikel阅读(1041)

    原创作者: litaocheng  

    进入Erlang的世界

    作为程序员,我们曾经闻听很多“业界动态”,“技术革新”,曾经接触很多“高手箴言”,“权威推荐”。这些正确与否,都已成过去!

    现在,让我们迎接Erlang盛宴!

    经历

    200711月在koders.com搜索代码时,发现*.erl格式的源文件,感叹开发语言的花样百出,此时,我觉得erlang是一个丑陋的小家伙,看名字就没有对它提起多少兴趣。

    2008年初的时候,公司的项目开发中,我有缘认识了ejabberd,一个采用Erlang开发的开源jabber服务器。我开始为其诱人的特性所倾倒。是时候认真看看Erlang到底什么样了!

    20084月,通过各种资料的搜集,了解,我决定系统的学习Erlang

    今天,通过4个月的认真学习,我已经熟悉了Erlang,已经在使用Erlang开发项目。作为C++程序员,我不敢妄自使用“熟悉”,“精通”之类的字眼,但是对于Erlang我可以很负责任的说,Erlang很巧,很强大!

    困惑

    面对一个新的事务,我们本性都会充满好奇,可是作为程序员,很多时候对于新的语言我都充满了抵触:这个新东西值得学习么?它会不会让我抛弃我的旧爱?它文档丰富么?其是不是很难理解?它的前景如何?…等等,相信大家跟我有一样的苦恼。

    但是,请听我说!我们是程序员,我们走在技术革新的最前沿。用户的产品,体验是通过我们来产生!我们不能畏缩不前,我们的固步自封,就是我们的公司,乃至整个我们的行业的停滞不前!口号可能有些响亮,但是认真思考,我相信朋友们一定有所感悟。

    Erlang是什么

    Erlang是什么是我们最先要面对的问题,只有清楚了它是什么,我们才能做出我们的决定。可见这个问题的重要性,它决定了很多读者是否会继续看下去!非常紧张。

    Erlang最初是爱立信为开发电信相关产品而产生。

    Erlang是一种面向并发(Concurrency oriented),面向消息(Message oriented)的函数式(Functional)编程语言。

    面向并发说明Erlang支持大规模的并发应用,我们可以在应用中处理成千上万的并发,而不相互影响。面向消息,其实是为并发服务!我们应该都熟悉多线程,熟悉加锁解锁操作,熟悉可能出现的资源竞赛与死锁。在Erlang的世界里,我们可以将轻轻的抹去这些令人苦恼的词汇。Erlang的世界,每个处理都是独立的个体,他们之间的交互仅仅靠消息!因此不会有死锁,不会有痛苦的编程经历。

    Erlang中一个非常重要的名词:Process,也就是我们前面提到的“个体”。它不是我们操作系统中的进程,也不是线程。它是Erlang提供给我们的超级轻量的进程。为了适应大规模并发的特性,Process需要能够快速创建,快速销毁。Process之间通信的唯一方法就是消息,我们只要知道一个Process的名字即pid,就可以向其发送消息。Process也可以在任何时候,接收消息。我们这样做只有一个目的:让我们的系统更加简单,用一种朴素的做法,实现一个高效的语言。

    Erlang是种函数式编程语言,对此我没有很深刻的理解,最明显的特征就是,Erlang中到处都是函数,函数构成了我们的产品的主体,把这些函数放到一个个的Process中去,让他们运行起来,那么就组成了我们朝气蓬勃的产品。

    Erlang支持对数据的位操作,拥有丰富的数据持久化机制。

    同时需要说明的是Erlang内建垃圾回收机制(GC)。

    Erlang语言特性

    简单小巧

    Erlang中只有8种基本的数据类型:

    Integerfloatatomreferencefunportpidbitstring

    同时提供2种复合结构:tuplelist,这就是Erlang的所有数据类型。

    模式匹配

    Erlang的函数中,某些语法中,我们可以使用Pattern匹配,这是一个非常好的特性,我们可以让代码自己去决定如何执行

    比如,我们定义一个函数,其告诉我们某种水果的价格:

    price(apple) -> 2.0;

    price(banana) -> 1.2.

    我们随后调用 price(Fruit),会根据Fruit变量的内容返回具体的价格。这样做的好处就是节省了我们的代码量,我们不用if…else…或者switch…case的来伺候了。也便于代码的扩展:加一个新的水果品种,我们只需要加一行就可以了。

    学习Erlang一个非常重要的内容就是模式匹配,但是请不要混淆,这个匹配和正则表达式没有任何干系。

    变量单次赋值

    这个是一个匪夷所思的特性,变量竟然只能单次赋值!是的Erlang中变量一旦绑定某个数值以后,就不能再次绑定,这样做的好处是便于调试出错。当发生错误时,某个变量是什么就永远是什么,不用顺藤摸瓜的查找谁修改过它,省了好多事情。唯一的麻烦就是需要一个信的变量时,你必须再为它想一个名字。

    丰富的libs

    Erlang中提供丰富的libs

    stdlib中包含大量的数据结构如listsarraydictgb_setsgb_treesetsdets

    mnesia提供一个分布式的数据库系统

    inets提供ftp clienthttp client/servertftp client/server

    crypto 提供加密解密相关函数,基于openssl相关实现

    ssl 实现加密socket通信,基于openssl实现

    ssh 实现ssh协议

    xmerl 实现XML相关解析

    snmp 实现SNMP协议(Simple Network Management Protocol

    observer 用来分析与追踪分布式应用

    odbc 使Erlang可以连接基于SQL的数据库

    orber 实现CORBA对象请求代理服务

    os_mon 提供对操作系统的监控功能

    dialyzer提供一个静态的代码或程序分析工具

    edoc 依据源文件生成文档

    gs 可以为我们提供某些GUI的功能(基于Tcl/Tk

    还有很多朋友提供了一些开源的lib,比如eunit,用来进行单元测试。

    灵活多样的错误处理

    Erlang最初为电信产品的开发,这样的目的,决定了其对错误处理的严格要求。Erlang中提供一般语言所提供的exceptioncatchtry…catch等语法,同时Erlang支持LinkMonitor两种机制,我们可以将Process连接起来,让他们组成一个整体,某个Process出错,或推出时,其他Process都具有得知其推出的能力。而Monitor顾名思义,可以用来监控某个Process,判断其是否退出或出错。所有的这些Erlang都提供内在支持,我们快速的开发坚固的产品,不在是奢望。

    代码热替换

    你的产品想不间断的更新么?Erlang可以满足你这个需求,Erlang会在运行时自动将旧的模块进行替换。一切都静悄悄。

    天生的分布式

    Erlang天生适合分布式应用开发,其很多的BIF(内建函数,相API)都具有分布式版本,我们可以通过BIF在远程机器上创建Process,可以向远程机器上的某个Process发送消息。在分布式应用的开发中,我们可以像CC++,JAVA等语言一样,通过Socket进行通讯,也可以使用Erlang内嵌的基于Cookie的分布式架构,进行开发。当然也可以两者混合。分布式开发更加方便,快速。ErlangProcess的操作,Error的处理等都对支持分布式操作。

    超强的并发性

    由于采用其自身Process,而没有采用操作系统的进程和线程,我们可以创建大规模的并发处理,同时还简化了我们的编程复杂度。我们可以通过几十行代码实现一个并发的TCP服务器,这在其他语言中都想都不敢想!

    多核支持

    Erlang让您的应用支持多个处理器,您不需要为不同的硬件系统做不同的开发。采用Erlang将最大限度的发挥你的机器性能。

    跨平台

    如同JAVA一样,Erlang支持跨平台(其目前支持linuxmacwindows19种平台),不用为代码的移植而头疼。

    我们仅仅需要了解平台的一些特性,对运行时进行优化。

    开源

    开源是我非常喜欢的一个词汇,开源意味这更加强壮,更加公开,更加的追求平等。开源会让Erlang更好。

    Erlang与外界的交互

    Erlang可以与其他的语言进行交互,如CC++,Java。当然也有热心的朋友提供了与其他语言的交互,如果需要你也可以根据Erlang的数据格式,提供一个库,让Erang与您心爱的语言交互。

    Erlang支持分布式开发,您可以创建一个C Node,其如同一个Erlang节点,前提是你遵照Erlang的规范。

    当然最常用的交互还是再同一个Node上,比如我们要调用某个lib,调用一些系统提供的功能,这时候主要有两种方式:Port和嵌入式执行。

    PortErlang最基本的与外界交互的方式,进行交互的双方通过编码,解码,将信息以字节流的方式进行传递。(具体这个通道的实现方式,根据操作系统的不同而不同,比如unix环境下,采用PIPE实现,理论上任何支持对应Port通道实现的语言都可以与Erlang进行交互)。Erlang为了方便CJAVA程序员,提供了Erl_InterfaceJinterface

    采用Port,您的代码在Erlang的平台之外运行,其崩溃不会影响Erlang

    嵌入式执行,通过Erlang平台加载,因此这是非常危险的,如果您的程序崩溃,没有任何理由,Erlang也会崩溃。

    Erlang应用场景

    分布式产品,网络服务器,客户端,等各种应用环境。

    Erlang也可以作为一种快速开发语言,进行原型开发。

    Erlang的学习过程

    1.         安装首先从Erlang官方网站,下载安装Erlanghttp://www.erlang.org/download.html

    linux:获取源代码,根据说明编译;windows:直接安装

    2.         认真阅读《programming erlang》(中文版图书已经问世),并不断动手练习书中的例程。

    3.         遇到问题时,不要退却,坚持下去找到解决办法

    4.         对语言熟悉时,浏览一些好的开源项目

    5.         有信心时,开始动手做一个小项目

    6.         不间断的与大家交流,共同提高

    可能遇到的困难:

    a)         对于语法的不适应?

    坚持看下去,代码继续写下去,我相信1个月,你会喜欢上Erlang的语法

    b)        有些数据类型不清楚?

    认真看资料,或者询问朋友,比如我

    c)        中文资料的缺乏?

    Erlang中文的资料会越来越多,此外,Erlang的相关的英文资料也比较容易理解,还是那句话,别怕麻烦

    Erlang开源项目

    排名不分先后

    • couchdb     基于文档的数据库,拥有RestfulAPI,MVCC,View,诸多特性
    • ejabberd    性能出众,使用广泛的Jabber开源服务器
    • mochiweb    轻便,高效的HTTP应用框架
    • nitrogen    基于事件的Web开发框架
    • rabbitmq    中间服务器,实现AMQP协议
    • yaws        高效的web server
    • etorrent    Bittorrent客户端
    • Scalaris           分布式的key-value存储
    • disco       Map-Reduce框架,Erlang Python

    遇到问题

    参看Erlang官方文档 http://www.erlang.org/doc/

    订阅Erlangmaillisthttp://www.erlang.org/mailman/listinfo/erlang-questions),进行提问

    Nabble提供的Erlang maillist存档中搜索(http://www.nabble.com/Erlang-f14095.html

    Google中搜索答案

    推荐阅读

    Erlang Design Principles http://www.erlang.org/doc/design_principles/part_frame.html

    Erlang Efficiency Guide http://www.erlang.org/doc/efficiency_guide/part_frame.html

    Erlang Programming Rules http://www.erlang.se/doc/programming_rules.shtml

    推荐网站

    http://www.erlang.org

    http://erlang-china.org

    http://www.planeterlang.org/

    http://www.erlangplanet.org/

    http://trapexit.org