在很多Web系统中,一般都可能提供一些图标的选择,方便配置按钮,菜单等界面元素的图标,从而是Web系统界面看起来更加美观和协调。但是在系统中一般内置的图标样式相对比较有限,而且硬编码写到样式表里面,这样给我们扩展使用有很多的不方便。基于这个原因,我想如果能够独立一个模块,自动根据图标生成图标CSS样式文件,并存储相应的记录到数据库里面,方便我们查询显示,那样我们使用起来就很方便了,最后有了这些数据,只需要做一个通用的图标选择界面,并可以在很多地方重用了。本文正是基于这个思路,开发了一个图标管理模块和图标选择界面,本文主要阐述这个开发过程和最终的效果展示。

1、图标样式生成管理

为了方便根据读取的图标文件列表,生成对应的图标样式文件,我们可以利用NVelocity组件,基于模板进行CSS样式文件的生成。关于NVelocity的使用,可以参考我多篇关于它的介绍,这个组件非常强大,我自己的代码生成工具也是基于它编写了很多模板进行代码生成,具体可以参考一下《使用NVelocity生成内容的几种方式》这篇文章。

1.1 图标样式文件准备

有了这些准备,我们可以定义一个模板的文件用来生成样式文件了,我们先看最终的样式文件效果。

.icon-table{background:url('table.png')no-repeatcentercenter;}.icon-telephone{background:url('telephone.png')no-repeatcentercenter;}.icon-user{background:url('user.png')no-repeatcentercenter;}.icon-view{background:url('view.png')no-repeatcentercenter;}.icon-word{background:url('word.png')no-repeatcentercenter;}

根据以上组织效果,我们可以定义一个模板内容如下所示。

#foreach($itemin${FileNameList}).${item.Text}{background:url('${item.Value}')no-repeatcentercenter;}#end##endforeach

其中FileNameList变量是一个基于名称和值的集合对象,我们遍历它进行生成就可以了。

1.2 图标样式的生成操作

有了模板,我们还需要组织好对应的文件目录,一般来说,Web的图标可以使用16,24,32这些标准大小的图表,适应不同场合的需要。

因此我们创建几个不同的目录,并放入对应的模板文件和图标文件。

生成图标样式文件的操作分为下面几个步骤:

获取对应目录的图标文件,转换为实际的对象格式集合,生成图标样式文件,存储图表样式到数据库方便查询。

这些操作我们在图标管理的控制器IconController里面增加方法完成,部分代码如下所示。

///<summary>///生成图标文件///</summary>///<paramname="iconSize">图表尺寸,可选16,32等</param>///<returns></returns>publicActionResultGenerateIconCSS(inticonSize=16){CommonResultresult=newCommonResult();stringrealPath=Server.MapPath("~/Content/icons-customed/"+iconSize);if(Directory.Exists(realPath)){List<CListItem>list=GetImageToList(realPath,iconSize);try{//使用相对路径进行构造处理stringtemplate=string.Format("Content/icons-customed/{0}/icon.css.vm",iconSize);NVelocityHelperhelper=newNVelocityHelper(template);helper.AddKeyValue("FileNameList",list);helper.FileNameOfOutput="icon";helper.FileExtension=".css";helper.DirectoryOfOutput=realPath;//指定实际路径stringoutputFilePath=helper.ExecuteFile();if(!string.IsNullOrEmpty(outputFilePath)){result.Success=true;//写入数据库boolwrite=BLLFactory<Icon>.Instance.BatchAddIcon(list,iconSize);}}catch(Exceptionex){LogTextHelper.Error(ex);result.ErrorMessage=ex.Message;}}else{result.ErrorMessage="没有找到图片文件";}returnToJsonContent(result);}

上面的方法很好的完成了对图标样式的生成和保存数据库的操作,这个生成操作主要就是基于模板化的生成,非常方便。

在构建名称值的集合的时候,注意图标样式名称,不能包含有 一些特殊的字符,如[]()这些符号需要去掉,因此可以通过下面的正则表达式替换方法进行去除。

stringdisplayText=Path.GetFileNameWithoutExtension(file);//文件名需要去除()和[]等符号displayText=CRegex.Replace(displayText,@"[)\];,\t\r]|[\n]","",0);displayText=CRegex.Replace(displayText,@"[(\[]","-",0);

最终,我们可以构建一个独立的页面,用来实现生成图标样式并保存的操作,界面如下所示。

界面操作代码如下所示。

//绑定按钮的的点击事件functionBindEvent(){$("#btnGenerateCSS").click(function(){$.messager.confirm("操作确认","您确认重新生成图标记录吗?",function(action){if(action){//图表尺寸variconSize=$("#IconSize").combobox('getValue');//alert(iconSize);varpostData="";$.ajax({type:'POST',url:'/Icon/GenerateIconCSS?iconSize='+iconSize,dataType:'json',data:postData,success:function(data){if(data.Success){showTips("操作成功");location.reload();}else{showError("操作失败:"+data.ErrorMessage,3000);}}});}});});}

2、图标的分页展示

为了有效查看我们生成在数据库的图标列表,我们需要一个合理的界面表现方式,用来显示图标信息。传统的使用datagrid的方式比较呆板,也不是很方便,所以我们需要自定义分页处理进行展现,基于重用一些优秀组件的原则,我侧重于使用一些现成的组件模块,MVC分页方面,考虑使用杨涛的MVC分页控件(http://www.webdiyer.com/mvcpager/),这个功能看起来很不错。

图表的展现方式,我希望通过easyui的这个例子进行展现一组图表的效果。

2.1 图表展现的界面效果

然后系统通过把它们进行分页处理,选择一些好的分页样式表现方式

最终实现的图表样式显示效果如下所示。

小图标效果如下所示。

大图标效果如下所示。

2.2 图标的分页处理操作

杨涛的分页控件,提供了很多绑定分页的方式,不过都主要是基于MVC的模型数据处理,在我的Web框架里面主要利用JS绑定数据,有 一定的差异,但是既然大家都是MVC应用,整合还是没问题的。

为了展现上面的效果,我们需要建立一个表单查询的内容,代码如下所示。

<fieldset><legend>功能操作</legend>@using(Html.BeginForm("select","Icon",newRouteValueDictionary{{"id",""}},FormMethod.Get)){<span>尺寸:</span><selectclass="easyui-combobox"id="IconSize"name="IconSize"><optionvalue="16">16×16</option><optionvalue="24">24×24</option><optionvalue="32">32×32</option></select><inputtype="submit"value="搜索(S)"accesskey="S"/>}</fieldset>

数据内容的展现,主要就是利用了easyUI的样式,创建一些linkbutton的代码,代码如下所示。这里注意的是,我也是用了model,它是PagedList<WHC.MVCWebMis.Entity.IconInfo>类型的。

也就是说,最终这个视图界面后台,是有一个模型的绑定的。

<divid="contents">@usingWebdiyer.WebControls.Mvc;@modelPagedList<WHC.MVCWebMis.Entity.IconInfo>@foreach(variteminModel){<ahref="javascript:void(0)"class="easyui-linkbutton"onclick="SelectItem(this,'@item.IconCls')"id="@item.ID"data-options="plain:true,iconCls:'@item.IconCls',size:'large',toggle:true"></a>}</div>

图标后台处理的控制器方法如下所示。

///<summary>///根据条件获取基于PagedList的对象集合,并返回给分页视图使用///</summary>///<paramname="id">分页页码</param>///<paramname="iconsize">图标尺寸</param>///<returns></returns>privatePagedList<IconInfo>GetPageList(int?id,int?iconsize=16){intsize=iconsize??16;intpageIndex=id??1;intpageSize=200;PagerInfopagerInfo=newPagerInfo();pagerInfo.CurrenetPageIndex=pageIndex;pagerInfo.PageSize=pageSize;stringwhere=string.Format("iconsize={0}",size);List<IconInfo>list=BLLFactory<Icon>.Instance.FindWithPager(where,pagerInfo);PagedList<IconInfo>pageList=pageList=newPagedList<IconInfo>(list,pageIndex,pageSize,pagerInfo.RecordCount);returnpageList;}///<summary>///根据条件获取分页数据集合,并绑定到视图里面///</summary>///<paramname="id">分页页码</param>///<paramname="iconsize">图标尺寸</param>///<returns></returns>publicActionResultSelect(int?id=1,int?iconsize=16){PagedList<IconInfo>pageList=GetPageList(id,iconsize);returnView("select",pageList);}

最后部分是分页部分的展现了,就是在底部展现各页的页码等信息了。

这个部分很简单,代码如下所示。

<div><div>共@Model.TotalPageCount页@Model.TotalItemCount条记录,当前为第@Model.CurrentPageIndex页</div>@Html.Pager(Model,newPagerOptions{PageIndexParameterName="id"},new{style="float:right",id="badoopager"})</div>

在分页的时候,可能很多时候,发现更新页面后,条件就消失了,这种情况是因为没有很好绑定条件的值到界面上,我们可以通过页面加载完成后,把URL里面的参数值赋值给控件就可以了。

$(function(){variconSize='@Request.QueryString["iconSize"]';if(iconSize!=undefined&&iconSize!=""){$("#IconSize").combobox('setValue',iconSize);}});

这样图表大小的条件就一直可以保持正确的内容,提交表单后依旧可以正常保持了。

3、图标的选择

既然生成了图标文件,并且构建了图标的展示界面,那么我们就需要在一些需要配置图标的地方,能够提供一个界面选择图标了。

绑定弹出选择图标界面操作,在EasyUI的基础上,使用了扩展对话框的操作,可以弹出一个外部页面的选择图标菜单。

functionSelectIcon(id,value){$.showWindow({title:'选择图标',useiframe:true,width:960,height:640,content:'url:/Icon/Select',data:{id:$(id),value:$(value)},buttons:[{text:'OK',iconCls:'icon-ok',handler:'doOK'//此方法在_content3.html中},{text:'取消',iconCls:'icon-cancel',handler:function(win){win.close();}}],onLoad:function(win,content){//window打开时调用,初始化form内容if(content){content.doInit(win);}}});}//绑定选择按钮的事件functionBindSelectIconEvent(){$("#tdIcon").click(function(){SelectIcon("#imgIcon","#WebIcon")});$("#tdIcon1").click(function(){SelectIcon("#imgIcon1","#WebIcon1")});}

选择好每个图标后,我们就会返回到主界面上,并设置好主界面上的图表样式,让它显示出我们选择的图标效果。