CSS设计器代码参考.1
星期一, 05月 10th, 2004
这里对前面讲的CSS设计器系统关键代码作一些小结,如果没有看过前面文章请先参看前文
解析CSS样式文件
这段代码主要作用是把CSS文件分解为多个样式类,并按名称/文本属性生产ClassItem对象,并保存在一个ArrayList(cssList)中(C#代码)
//读取文件 FileInfo theSource= new FileInfo (@m_filePath); StreamReader reader = theSource.OpenText(); //将文件流转化为文本 m_cssText = reader.ReadToEnd(); reader.Close(); //定义CSS文本分割符 char[] delimiters = new char[] { '{','}'}; int iCheck = 1;string className = null; //将文本转化为ArrayList foreach ( string substring in m_cssText.Split(delimiters)) { if (iCheck%2==0) //当iCHeck为偶数时,字符串为样式属性内容 //将解析的样式名和属性作为ClassItem对象存入cssList cssList.Add( new ClassItem ( className, substring.Trim() ) ); else //当iCHeck为奇数时,字符串为样式名,暂存 className = substring.Trim(); iCheck++; }
交互界面构建
交互界面由Javascript通过XmlDocument读取Xml文件动态生成。
首先要读取XML文件,然后遍历整个XML文件,先遍历样式分类,再对每个分类遍历其下的所有样式属性。比较关键的代码是对XML的遍历,下面是对样式分类的遍历代码。
//LoadXML是XML文件读取函数 var dom = LoadXML("css.xml"); //通过XPath和selectNodes方法返回一个XMLDOMNodeList对象 var oNode = dom.selectNodes("//Category/Name"); //获取该对象长度,即XML文档中该路径节点的数量 var intCategory = oNodes.length; for (i=0; i<intCategory; i++) { //获取集合中的节点 oNode = oNodes.nextNode; if (oNode != null) { //样式分类界面构建代码-略 …… } }
样式输入控件构建函数,该函数作用是根据XPath路径查询XML定义,生成交互控件
function BuildInput ( path ) { var str=""; var aNode=null; var attValue=null; //通过selectSingleNode返回符合条件的第一个节点 var actNode = dom.selectSingleNode(path+"ActionType"); var nameNode = dom.selectSingleNode(path+"CssName"); //如果属性为选择输入,则读取SelectItems,并构建select控件 if (actNode.text=="select") { str += "<select id='"+nameNode.text+"' name='"+nameNode.text+"'class='eSelect'>"; //查询该项的所有选择列表项 var itemsNodes = dom.selectNodes (path+"SelectItems/Item"); str += "<option value='-1'>未设置</option>"; for (ii=0;ii<itemsNodes.length;ii++){ aNode = dom.selectSingleNode (path+"SelectItems/Item["+ii+"]"); //如果该项含有Name属性则在列表中显示Name属性值 attValue = aNode.getAttribute("Name") var txtNode = dom.selectSingleNode (path+"SelectItems/Item["+ii+"]"); if (attValue==null) str += "<option value='"+txtNode.text+"'>"+txtNode.text+"</option>"; else str += "<option value='"+txtNode.text+"'>"+attValue+"</option>"; } str += "</select>"; } else //如果属性为其他模式,则构建input输入,设置class属性为ActionType { str = "<input name='"+nameNode.text+"' id='"+nameNode.text+"' class='"+actNode.text+"'>"; } return(str); }
asp.net开发技巧
星期四, 05月 6th, 2004
不断学习的过程中,经常遇到一些代码编写技巧性的东西,虽然通常不是什么特别困难的技术问题,不过也十分重要。
为避免遗忘并方便查证,特记录于此。
在页面中直接发文件到客户端
说明: 将下面代码加入干净的aspx页或隐藏代码页即可(此处假设页面为download.aspx);
效果: 链接到地址[download.aspx?file=filename]直接产生下载;
目的: 与直接链接文件地址下载方式比较,可以在下载前加入代码,统计下载数;另外,根据需要可以改写参数(例如改为数据库中该下载文件记录的id),做简单的代码处理,就可以在一定程度上隐藏下载地址,防止盗链……
private void Page_Load(object sender, System.EventArgs e)
{
string path = Server.MapPath(Request.Params["File"]);
System.IO.FileInfo file = new System.IO.FileInfo(path);
Response.Clear();
Response.AddHeader(“Content-Disposition”, “attachment; filename=” + file.Name);
Response.AddHeader(“Content-Length”, file.Length.ToString());
Response.ContentType = “application/octet-stream”;
Response.WriteFile(file.FullName);
Response.End();
}
CSS设计器之界面交互
星期四, 04月 29th, 2004
整个操作交互过程,除了最后保存文件外,其他都是由javascript完成。
首先DesignerBuild函数读取XML样式属性定义文件,构建整个设计器界面。然后Init函数读取服务器端赋给设计元素的Style属性,并把属性作为输入控件ID在设计器中查找并赋值,完成初始化。
在操作过程中,根据输入控件的样式类Class,触发绑定的HTC组件,做相应的客户端操作。
最后再读取设计元素的style属性,保存。
设计器界面
不同的设计元素
不同输入控件的不同class属性(根据XML中ActionType生成)触发不同HTC组件,实现不同输入模式。
由于商业原因,这里不便提供源代码;我将在后面提供部分关键代码供参考。
CSS设计器之XML样式属性定义
星期二, 04月 27th, 2004
CSS样式中包含很多属性,设计器中当然要包含相应的属性类型;那么这些属性信息从哪里来呢?
采用XML定义是一种很自然就会想到的方式。
经常使用DW和VS.NET,所以在交互设计上采用了类似的模式;先将样式属性分类,再设置详细属性。
CSS属性是比较复杂的,如果要完全按照DW或VS.NET的模式,实现会比较复杂。为了简化,我把值的输入简化为两种形式,选择和文本输入。对于选择,直接在XML文件中定义;对于文本输入,抽象几种输入类型,在设计器生成时根据类型设定不同的HTC组件操作。这样就将一些复杂的属性输入封装到 HTC组件中,整个构架就简洁起来。
XML文件描述
首先是属性分类
<cssdesign> <category> <name>文字</name> <style> <name>字体</name> ...... </style> <style> <name>样式</name> ...... </style> ...... </category> <category> <name>背景</name> <style> <name>颜色</name> ...... </style> ...... </category> </cssdesign>
系统分为文字、背景、文本、位置、布局、方框、边框和其他,每种类型有一个Name子元素和若干Style子元素。
每个Style子元素表示一个Style属性,结构如下
<style> <name>字体</name> <cssName>font-family</cssName> <actionType>select</actionType> <selectItems> <item>verdana,arial</item> <item Name="宋体">SimSun</item> <item Name="黑体">SimHei</item> </selectItems> </style> <style> <name>大小</name> <cssName>font-size</cssName> <actionType>select</actionType> <selectItems> <item>12px</item> <item>14px</item> <item>9px</item> </selectItems> </style> <style> <name>颜色</name> <cssName>background</cssName> <actionType>input_ColorSelect</actionType> </style>
Name为该属性的描述名称,在设计器中为文本描述;
CssName为属性名,在设计器中即输入字段的ID;
ActionType为属性设置方法,在设计器中为输入字段的样式类名,该样式中含有Behavior属性,制定HTC组件;
SelectItems为选择项,如果ActionType为Select,将会在此列出选择项;其子元素Item如果含有Name属性,将显示在设计器中,否则直接显示该元素的文本内容
框架图
CSS设计器之样式表操作类
星期一, 04月 26th, 2004
为了操作样式表,设计了一个简单的样式表操作类。功能主要是解析操作指定样式表文件,实现对样式类的添加、修改、删除、保存。
机制:读取Web服务器上某样式表文件,将文本转化为一个ArrayList,数组元素为自定义的ClassItem对象,包含Name和Text属性(Name即样式名称,Text即样式的内容);然后通过对ArrayList操作,控制样式,最后保存。
由于在服务器段我们不作具体样式定义,因此该类只操作到样式类级别,不涉及样式属性和值。
下面提供该类的UML图 ClassItem 是一个结构体,仅包含两个属性;

CSS设计器之流程
星期五, 04月 23rd, 2004
最近做了一个CSS设计器,主要功能是在web界面上操作设计CSS样式表,目的是方便用户自定义系统界面。
其实我个人看法这个东西并没有太大必要,对于最终用户来说,一般不熟悉网页制作,是不可能进行这种操作的,而且就系统整体来考虑,也不应该给用户这种权限。另外,相对于本来就比较紧张时间资源来讲,花这么多时间,实现这种用户需求优先度较低的功能,实在不合算……
奈何项目经理雄心勃勃,在大而全的方针指导下,不得不做啊。
月初就作的差不多,来总结一下吧
流程再简单说明一下
C#的四个基本技巧
星期四, 04月 22nd, 2004
1.如果可能尽量使用接口来编程
.NET框架包括类和接口,在编写程序的时候,你可能知道正在用.NET的哪个类。然而,在这种情况下如果你用.NET支持的接口而不是它的类来编程时,代码会变得更加稳定、可用性会更高。请分析下面的代码:
private void LoadList (object [] items, ListBox l)
{
for (int i = 0; i < items.Length;i++)
l.Items.Add (items[i].ToString ());
}
这个函数从一个可为任何对象的数组中加载ListBox,这段代码被限定为只能使用数组。假想过些时候你发现那些对象存在数据库中,或别的集合中。那么你需要修改程序来使用不同的集合类型。如果你用ICollection接口来写那段程序,你就不用修改那段程序了,对于任何实现 ICollection接口的类型它都能很好的工作:
private void LoadList (ICollection items,ListBox l)
{
foreach (object o in items)
l.Items.Add (o.ToString ());
}
ICollection被数组和所有System.Collection中的集合实现。此外,多维数组也支持ICollection接口。如果那还不够的话,数据库.NET类同样支持ICollection接口。用接口写的这个函数不用需改就可以才许多中情况下使用。
2. 使用属性代替原始数据
因为属性已经成为语言本身的元素,所以声明数据元素时它的作用域等级没有必要大于private。因为代码本身会把属性看成数据元素,你并没有失去使用简单数据类型的便利性 。相反它会使你的代码更加灵活功能更加强大。属性使你的数据元素封装性更好。属性可以让你使用lazy evaluation来返回数据。lazy evaluation的意思是当用户请求时才计算它的值,而不是一直保留着它。
最后,属性可以是virtual也可以是abstract。你也可以在接口中定义属性。
这里还有维护方面的因素应当注意:尽管操作两者的方法是一样的,但是你把一个数据元素变成属性,那么原先客户端的程序便不能访问服务端的新版本程序了。实际上对于在Web service中你想实现序列化的值你可以把它们变成属性来使用:
private int TheMonth = 0;
[XmlAttribute ("Month")]
public int Month
{
get {
return TheMonth;
}
set {
TheMonth = value;
}
}
简单通过属性就可以使你的所有数据元素私有化。
3. 在Producer/Consumer 的Idiom中使用Delegate
当你生成一个实现producer idiom类的时候,使用deletate来通知consumer。这种方法相对于用接口更加灵活。Delegate是多点传送的,所以不用加额外的代码你就何以支持多用户。相对于用接口这样做可使类之间的耦合性降低。
下面的类处理键盘输入并把它传给所有的registered listeners:
public class KeyboardProcessor
{
private OnGetLine theFunc = null;
public OnGetLine OnGetLineCallback {
get {
return theFunc;
}
set {
theFunc = value;
}
}
public void Run (){
// Read input.
// If there is any listeners, publish:
string s;
do {
s = Console.ReadLine ();
if (s.Length == 0)
break;
if (theFunc != null){
System.Delegate [] funcs =theFunc.GetInvocationList();
foreach (OnGetLine f in funcs) {
try {
f (s);
} catch (Exception e) {
Console.WriteLine
(“Caught Exception: {0}”, e.Message);
}
}
}
} while (true);
}
任何数目的listeners都可注册到producer,它们所要做的只是提供一个特定的函数:deletate。
4. 注意初始化顺序
C#中对于一些变量声明加入了initializer的概念。它们在构造函数之前被执行,实际上变量在基类的构造函数执行前之前被初始化。
所以,在初始化变量的时候不要用基类中的数据,因为它们还没有被构造。
JSP / Eclipse / 重构
星期日, 04月 11th, 2004
这两天看了看JSP,查资料安装调试系统花了半天,Tomcat5.0.19 + SqlServer2K JDBC + Eclipse2.1.2。
JSP粗略看了看,感觉几点
- 细节琐碎,很多代码细节比较琐碎,写起来很麻烦;
- 命名不友好,一些方法、类等等命名不够友好,直观看不清楚什么意思,可能是我习惯了.NET的命名,不过记得我初学.NET时对命名理解还是很清楚的啊;
- 错误异常很难懂,我的英文虽然不咋地,但是看计算机英语也很久了,一般都没有什么问题,不过tomcat的Erro页面完全没看懂……
可能是我还不习惯Java的文化吧
我对java强大的企业级开发技术很有兴趣,以后还要多花时间来看看。
Eclipse这个IDE虽然很多地方不如VS,不过在重构应用上有很多让我惊喜赞叹的地方,她对不同项目对象包括项目、包、类、方法、属性等等都有不同的重构应用,还有JUnit测试,不知道.NET什么时候才能具备这些特性……
Eclipse截图两张
MSDN中文网站推出
星期五, 04月 2nd, 2004
很让人兴奋的消息,到了3.31去看,虽然早有心理准备,知道不可能有太多内容,但还是有几分失望,内容太少了点,还是继续看英文版吧.
网站上还是有些好东西的,这周看了不少.
应用程序设计指南:从 N 层到 .NET
概要描述了Windows DNA构架和.NET构架下的设计,讲的比较清楚,可以看看,清晰一下.
领悟Web设计模式
一篇Web设计模式入门文章,浅显易懂,如果刚入门可以看看参考一下.
如何快速实现HTML编辑器.NET组件
过于快速的东西总是不太稳妥的,在稳定性和性能上会损失一些,不过这个例子可以初步了解一下如何封装一个简单的组件.
大数据量下的分页
两种大数据量分页方法,具有参考价值,或者直接照搬也不错啊
使用NUnit在.Net编程中进行单元测试
不错的文章,以前没做过NUnit的单元测试,要试试.
利用数据库模版创建方便部署的.Net项目调试环境
数据库部署,以前没这么做过,要试试!
还有很多,慢慢看.
XML/XSL实现界面自定义
星期二, 02月 24th, 2004
最近比较忙……
公司的项目目前进入了代码开发阶段,不过很多构架设计上的东西都还不清楚,我觉得应该还算是设计阶段。
目前系统要实现完全自定义界面,按项目经理说这个搞出来了,后面的业务界面就不用每个开发了。界面的实现方式是XML/XSLT/CSS的实现,而且最后要达到可视化设计实现。项目经理描述的是,针对不同的业务逻辑,产生不同的XML,然后用匹配的XSLT进行解释,生成aspx页面。
坦白的说,这个描述是不是反映了项目经理的原意,我也不太清楚,因为我一直也没弄明白整个构架实现的机制。只是我觉得在这种从上到下都不熟悉XML/XSLT,只是因为大约的了解,就贸然采用方案,对于这样一个时间紧迫的项目而言,风险实在不小。
上面的实现,说来还仅仅是难度较大、实现困难,但是希望象普通web编辑器那样可视化生成XSLT,那几乎就是不可实现的了。XSLT并非仅仅是对外观的格式化描述,还带有很多可编程元素,目前甚至有的系统完全采用xslt作为业务逻辑控制,可想其复杂性。目前还没有哪个软件能够实现可视化操作的,当然从功能和应用本身来说也没有这个必要。
我很担心因为技术难度过大而导致项目风险的大大增加,延期是肯定的了,只是希望最后不要失败才好。我做事情通常会先确保一个必须达到的最低标准,然后在比较有把握的情况下作锦上添花的工作。这算是比较保守吧,毕竟这不是我一个人的事情,有责任在。
目前我做一个CSS生成器,基本就是模仿VS.NET或DW的CSS生成器。计划采用XML/XSLT/XSD/Javascript开发,利用 XSD作数据约束,XSLT/JS作界面和交互控制,XML保存数据。我目前对具体技术还不清楚,不知道这么构架是否可行……先看书吧……


