web 2.0

ASPNET MVC表格呈现利器:MvcContrib.UI.Grid

ASPNET MVC框架现在日趋流行,最近我也刚完成一个用ASPNET MVC框架做的项目,现在想做一些阶段性的总结。

很多原来在WinForm下面的流行控件例如GridView,ListView,Repeater等表格呈现控件在ASPNET MVC下已经不能使用了,官方并没有提供现成的控件以供使用,因此我们也许经常会aspx页面中使用例如 <% For Or While语句 %>来呈现我们的表格了。但是一旦这样的页面多了,我们会发现这样还是比较繁琐且费时的。

在老赵的ASPNET MVC课程里面介绍过一个很有名气的类库MvcContrib。里面就有一个比较强大的类Grid来专门呈现这样强类型的数据的,在我的项目中,我也大量的采用了Grid的呈现方式,发现其还是非常好用的,而且扩展起来也是非常的方便的。

其实MvcContrib类库是一个很强大的类库,提供了诸如Ioc(控制反转)、ModelBinder、Filter、各种Input“控件”以及Grid,有兴趣的朋友可以去http://mvccontrib.codeplex.com/去获取更多信息。

 

从Grid使用说起

我们首先从Grid(MvcContrib 下的Grid类,再次简称Grid,下同)的使用说起,做过Web开发的人都知道,表格式由行和列组成,而行又通常区分为标题行(Head)、数据行和尾行三部分。Grid是通过一个名叫ColumnBuilder的类来实现IGridColumn列的累加,而IGridColumn接口则包含了控制单元格属性的诸多功能。我们从一段简单代码说起

 

<%= Html.Grid(Model)
        .Columns(c =>
            {
                c.For(x => x.CompanyName).Named("公司名称").Attributes(@class => "w10");
                c.For(x => x.City).Named("城市").Attributes(@class => "w8");
                c.For(x => x.ContactName).Named("联系名称").Attributes(@class => "w8");
            }
        )
        .Empty("暂无数据").RowStart(c => string.Format("<tr class='{0}'>", c.IsAlternate ? "alt" : "")) 
    %>
这是一段较为简单的代码,比较容易看出来呈现的是三列,首先我对代码做一个简单说明。

Grid(Model) : HtmlHelper的扩展方法,实例化Grid类,包装数据,返回IGrid<T>接口,IGrid<T>接口继承了IGridWithOptions<T>接口。

Columns(…) : IGridWithOptions<T>接口提供的方法,作用是构建表格的列。

For(…) : ColumnBuilder<T>方法,返回IGridColumn<T>接口,作用是构建列,从而为后续的方法提供链式支持。

Name(…) : IGridColumn<T>方法,指定列名显示内容。

Attributes(…) : IGridColumn<T>方法,指定单元格的属性

Empty(…) : IGridWithOptions<T>接口提供的方法,作用是当列表为空时显示的内容(提示)。它和Columns方法一样同为链式方法(即返回IGridWithOptions<T>自身)。

RowStart(…) : HtmlHelper针对IGridWithOptions<T>的扩展方法,作用是自定义行的开头部分(即Tr)。

 

显示效果:

basegridDome

 

源码分析

上面只是一个简单的演示,其实提供的方法远比这多得多,要想更好的使用Grid,我们需对其源码进行分析。

Grid在设计上采取的面向接口编程,大大降低了耦合性,经过HtmlHelper进行扩展的方法主要是针对两个接口进行的,一类是IGridColumn<T>,另一类是IGridWithOptions<T> 。我们在使用过程中通过VS2008的智能提示留意一下他们各自的返回值,因为返回的也是同一个接口,这样也就很好的提供了链式的方法,下面我久别分别说说这两类接口。

IGridColumn<T>主要是针对特定列以及列下单元格的控制,接口的方法如下(为了便于理解,我添加了注释):

 

Action<RenderingContext> CustomHeaderRenderer { get; set; }
Action<RenderingContext, T> CustomItemRenderer { get; set; }

//定义单元格附加属性
IGridColumn<T> Attributes(Func<GridRowViewData<T>, IDictionary<string, object>> attributes);
//定义一个委托,指定单元格内容是否显示
IGridColumn<T> CellCondition(Func<T, bool> func);
//是否对单元格内容进行HTML编码
IGridColumn<T> DoNotEncode();
//对列名称进行分离(老外的名字一般由两部分组成)
IGridColumn<T> DoNotSplit();
//格式化单元格内容,示例:.Format("{0:C}")
IGridColumn<T> Format(string format);
//定义头部(单元格)附加属性
IGridColumn<T> HeaderAttributes(IDictionary<string, object> attributes);
//定义列名
IGridColumn<T> Named(string name);
//指定该列是否显示
IGridColumn<T> Visible(bool isVisible);

后面我添加过注释的方法相对来说比较容易,我就不再赘述,这里我们需要留意的是前两个Custom方法,分别是用来定义列头和单元格的,在HtmlHelper扩展方法中对应的是HeaderAttributes和Attributes方法,值得一提的它这里用到了名曰Hash的一个类,我们来看看其扩展方法签名:

public static IGridColumn<T> HeaderAttributes<T>(this IGridColumn<T> column, params Func<object, object>[] hash)
{
    return column.HeaderAttributes(new Hash(hash));
}
public static IGridColumn<T> Attributes<T>(this IGridColumn<T> column, params Func<object, object>[] hash)
{
    return column.Attributes(x => new Hash(hash));
}

再来看看Hash 类的写法

public class Hash : Hash<object>
    {
        public Hash(params Func<object, object>[] hash) : base(hash)
        {
        }
    }

public class Hash<TValue> : Dictionary<string, TValue>
    {
        public Hash(params Func<object, TValue>[] hash)
            : base(hash == null ? 0 : hash.Length, StringComparer.OrdinalIgnoreCase)
        {
            if (hash != null)
            {
                foreach (var func in hash)
                {
                    Add(func.Method.GetParameters()[0].Name, func(null));
                }
            }
        }

public static Dictionary<string, TValue> Empty
        {
            get { return new Dictionary<string, TValue>(0, StringComparer.OrdinalIgnoreCase); }
        }
    }

这里的Hash类继承了Hash<object> 类,而Hash<object> 类又继承了Dictionary<string, TValue> 类,再看看Hash<object>添加字典项的方法,留意这一句:

Add(func.Method.GetParameters()[0].Name, func(null));

它是遍历Func<object, TValue>数组后用反射的方法获取匿名方法的参数名称作为字典的Key(这里是string型),而Value则是通过执行匿名泛型函数func(null)得到的。所以这就是前面示例中Attributes(@class => "w10")中的写法,它获取方法的参数名称“Class”作为Key,而方法的返回值“w10”即是字典的Value了,是不是设计的很巧妙呢。

有了这个Hash类,我们在写IDictionary<string, object>属性的时候就方便多了,下面是几个示例:

 

<%-- 指定单元格css为grid_cell,id为gridcell_id,合并2列 --%>
.Attributes(new Hash(@class => "grid_cell", id => "gridcell_id", colspan => "2"))
<%-- 指定Grid表格css为grid,单元格间隙为2,间距为0 --%>
.Attributes(new Hash(@class => "grid").Add<int>("cellpadding", 2).Add<int>("cellspacing", 0))
<%-- 定义表头列的样式为 居中,加粗13像素 Verdana字体,点击后触发排序事件 --%>
.HeaderAttributes(new Hash(Style => "text-align:center;font:bold 13px/20px Verdana;", onclick => "javascript:sort()"))
 

另一类接口IGridWithOptions<T> 则是对Grid的外围如行属性,表格属性的扩展,同样我也做了注释。

[EditorBrowsable(EditorBrowsableState.Never)]
IGridModel<T> Model { get; }

//定义Grid属性
IGridWithOptions<T> Attributes(IDictionary<string, object> attributes);
//构建ColumnBuilder,对列(IGridColumn<T>)进行累加
IGridWithOptions<T> Columns(Action<ColumnBuilder<T>> columnBuilder);
//空数据时显示的文字内容
IGridWithOptions<T> Empty(string emptyText);
//定义头行属性,这里与html元素对应的应该是<tr>而不是<td>
IGridWithOptions<T> HeaderRowAttributes(IDictionary<string, object> attributes);
void Render();
//定义采取哪一种呈现器(IGridRenderer<T> )进行呈现
IGridWithOptions<T> RenderUsing(IGridRenderer<T> renderer);
//定义行属性,与HeaderRowAttributes的区别在于不是头行
IGridWithOptions<T> RowAttributes(Func<GridRowViewData<T>, IDictionary<string, object>> attributes);

标签: ,

javascript获取当前URL信息

javascript获取URL中的各种参数以及对URL进行一些特殊处理:
 
   1: //设置或获取对象指定的文件名或路径。
   2: alert(window.location.pathname);
   3:  
   4: //设置或获取整个 URL 为字符串。
   5: alert(window.location.href);
   6:  
   7: //设置或获取与 URL 关联的端口号码。
   8: alert(window.location.port);
   9:  
  10:  
  11: //设置或获取 URL 的协议部分。
  12: alert(window.location.protocol);
  13:  
  14: //设置或获取 href 属性中在井号“#”后面的分段。
  15: alert(window.location.hash);
  16:  
  17: //设置或获取 location 或 URL 的 hostname 和 port 号码。
  18: alert(window.location.host);
  19:  
  20: //设置或获取 href 属性中跟在问号后面的部分。
  21: alert(window.location.search);

摘自:http://www.ruofeel.cn/344.html
joyaspx 标签:

标签: ,

高版本Windows系统如何安装A卡(启用photoshop cs4的硬件加速)

前一阵子安装了photoshop cs4,据说重要的一个新功能就是启用了硬件加速(Enable OpenGL Drawing),欢喜之下我在我的两台机器上都安装了,两台机器都是A卡(HB5360和HB3850),结果发现vista下能正常打开该功能,但是在windows7系统下就不可用了。刚开始我还以为是photoshop安装的不正确正想重装呢,后来仔细一向觉得很可能是显卡驱动问题,因为我的显卡驱动是系统自带默认安装的。

windows7系统能默认安装上许多A卡的基本驱动,但不一定是最佳最全的驱动,这也是我安装的photoshop cs4不能开启硬件加速的原因。于是我去官方网站下载了最新的驱动并安装。A卡的驱动在高版本windows系统(windows2008、windows7)下安装一直以来都是一件很头疼的事情,常规的图形化安装向导是不能成功安装A卡的(至少我碰到过的多台机器都是这样),后来在一个国外论坛上看到了一个命令行的安装模式对我很有启发,下面是我自己的安装方法。

A卡安装方法:

1、解压驱动包,例如至 C:\ati。

2、命令行进入其bin目录。我这里是“C:\ATI\SUPPORT\9-1_vista32_dd_ccc_wdm_enu_74233\Driver\Bin”;

3、输入指令:ATISetup.exe -Install -output screen

详细参数情况可以通过 atisetup -?来查看。安装过程中会在命令行里面看到安装进度,安装结束之后会弹出一个网页版的安装报表说明各个模块的安装情况。

通过重新安装A卡驱动,再打开photoshop一看,OpenGL加速已经可用了,大功告成!

标签:

开博第一篇

作为Web开发人员,一直以来都想拥有一个输入自己的博客,其实这个想法都已经酝酿很长时间了,最开始是想自己编写一个建议博客程序,这样既可以锻炼写程序能力也方便以后的扩展和维护,可是后来不是由于工作较忙就是自己惰性太重这件事情一直搁置到现在。后来倾向于.net开源博客,通过几个较为有名的博客程序的对比,我选择了blogengine.net,相比以前的1.0版本,现在无论是在通用性、扩展性和易用性方面都有了长足的进步,初步浏览了一下源代码,感觉非常不错,有机会我会写一些blogengin.net的研究心得方面的文章。

接触.net程序已经有两三年的,个人自认为是一个比较喜欢钻研新技术新事物的人,但同时也有眉毛胡子一把抓的味道,技术抓不住主干,知识的体系结构也没有得到一个良好的梳理,总结起因应该是不善于总结和归纳。现在是一个知识爆炸的年代,技术的更新非常快,做技术的也是无时无刻不在学习,这也意味着遗忘速度也在加快,如果不及时做一些总结和记录,相信也将会做大量重复的无用功。正因如此,我需要用博客来即使记录自己的一些心得,也许有一些领悟存在一些偏差,但是这是我自己的领悟,我应该用文字来记录。

我的博客初步定位为以技术文章为主,个人生活、日志为辅。

标签: