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属性,将显示在设计器中,否则直接显示该元素的文本内容

框架图

XML源文件

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的概念。它们在构造函数之前被执行,实际上变量在基类的构造函数执行前之前被初始化。

所以,在初始化变量的时候不要用基类中的数据,因为它们还没有被构造。

生命中不能承受之痛 2

星期四, 04月 15th, 2004

下面也是一种

………

门口响起了钥匙在锁孔里转动的声音,先生回来了。他没有象往常一样地一进门就喊:妞妞,妞妞,我回来了!饿死了!吃什么呀?他坐在沙发里发呆,我喊了他几声,他没有反应,我走过去一看,他神情黯然地委顿在沙发的一角,衣服上血迹斑斑。我大吃一经,忙问:“发生什么事情了?”他摇摇头说:“没什么,下班前处理了一个交通事故,心情不好。你先吃饭吧,回头跟你说。”“你呢?”“我不想吃。”

这可是没有过的事情。先生是个交通警察,在事故科工作已经五、六年了,对于生离死别、阴阳两隔,用他自己的话说是已经有些麻木了;不用说他,就连我,对那些卷宗里血淋淋的照片都已经有些漠然。他的办公室常有悲悲切切的人来哭诉,他却总能在复议时做到不掺杂感情。我是个爱哭的女人,偏偏先生对于眼泪早已有了职业的免疫力,他说要是每个事故他都要为每个逝者陪眼泪的话,他早就活不下去了,但是今天不同,他分明是掉过泪了。

接下来的这个故事就来自于我的先生,一个交警的口述。

我是在4点03分接到指挥中心的报告:在解放路距离交通指挥信号灯400米处,有一辆自备桑塔纳2000和一辆载货微型卡车发生猛烈的追尾碰撞事故。因为事故发生地点离我们很近,我和小王很快就赶到了现场,等我们到的时候,120还没有来,我们就赶紧救人。肇事车的司机早已不知去向,车门洞开,追尾车里有两个人,一男一女,男的血流满面,样子很恐怖,恐怕是所戴的眼镜片扎伤了双眼,女的看起来还好,正和过路的人一起把受伤的男人往外抱。由于猛烈的碰撞,桑塔纳的车头严重变形,男人被卡在驾驶位上,估计是腿断了,不能动弹。我叫小王先把女人送往医院救治,女人不肯,只是发疯似的抱住男人的上半身。我和小王拿来撬杠,总算把男人弄出来了。

这时我发现女人的嘴角溢出血来,唇色苍白。凭我的经验,这恐怕不是什么好征兆。
去医院的路上,刚好碰上下班高峰,路有些堵,女人坐在后座上抱着那个男人,男人痛苦地呻吟着,两个人的手指紧紧地纠结在一起。女人的嘴角不断地有血沫涌出,顺着下巴往下滴在男人的衣服上。她紧紧地抿住嘴,泪不停地往下掉,却什么也没有说,脸上的神色有痛苦也有不舍。

医院的急救人员早已在大门口待命,就在医护人员抱着男人往外抬的时候,女人一头栽倒在水泥地上,大口大口的鲜血从她的嘴里涌出来。我和小王立刻去抱她起来,我可以断定她肯定是肋骨断裂,并且已经刺伤了内脏。她这样的伤势却还能挺到这里,我不得不为人的潜能的张力叹服。她有些神志不清了,她一把捏住我的手,说了一句话:亲爱的,用我的眼睛去看世界。我的鼻子一酸,落泪了。两个人都被推进去了,我叮嘱小王通知家属,办理手续,我立刻驱车赶回现场勘察。现场满地的玻璃和车身上散落下来的碎片,斑斑的血迹说明了这个事故的惨烈。经现场勘察,我发现事故有些蹊跷。从刹车印和碰撞的痕迹来看,这个事故有着不平常的地方。第一,一般来说,追尾事故车头受损位置应该在右边,也就是副驾驶室的位置,因为司机往往是最先觉察危险的人,因为处于保护自己的本能会往左打方向,以减少事故对自己的伤害,但是这辆车的碰撞位置是中间偏左,致使驾驶位受损严重。

这种情况只会发生在来不及避让的情况下,但是从长长的刹车印来看,他完全有时间避险。第二,刹车印和散落的碎片的分布位置说明男人在前车刹车灯未正常工作而停止的时候,他已经本能地往左打了方向,但是他最后还是往右打了方向,把自己撞了上去。而后几个现场的目击者证实了我的推断。这只能说明一个问题:男人先是出于本能往左边打了方向,以期避开危险,但是,他立刻意识到这样他会伤害到身边这个女人,于是,他又猛烈地往右打方向,试图把女人往生的方向推一把,但是人的反应速度根本及不上车速,在他还没有完全打过方向之前,车已经撞到了。据我刚才在医院门口见到的一幕,恐怕事情没有男人想象的那么乐观。这个女人在车上的表现,恐怕她已经知道自己不能生还,可能她那时侯就是紧紧抿住嘴不让翻涌的血喷出来呢。

这时小王打来电话,女的刚死,男的还在抢救。女的是因为折了的肋骨刺穿了肺还有脾脏破裂引发的大出血。男的双眼扎伤,肋骨断了一根,双腿也折了。院方正考虑根据女的遗愿,把角膜移植给幸存者。

先生说完了,看着我:“我从来没有遇到过这样的事故,这让我对人有了新的认识。”

我的眼睛湿了。

这是从网上转来的,让我莫名感动……故事看来似乎真实的,其中女的说得那句话有些文学化,估计是写的人过于修饰了一些。

gf年纪不算小了,不过是一个很单纯的人,经常遇到一些不顺利的事情就有些情绪化,总说人生太过艰难,随口说些生生死死之类的言语;虽然我很理解她的心情,体谅她的情绪,总是开导劝解,但是心里难免难受一下……

生死之事,不是这么随意说的……

生命中不能承受之痛

星期一, 04月 12th, 2004

最近,父亲60寿就快来了……

家里似乎没有过什么生日,从小就没有关于过生日的记忆,小时候甚至不清楚我的生日是什么时候。模糊中有个记忆似乎是10月某天,直到高考填报时看见户口才发现原来是9月某天……

前段时间母亲提及父亲60寿,让我感到惊异……恍惚中父亲似乎还当壮年,怎么就寿至甲子了?电话里,母亲提到父亲最近时间多病,和我记忆中身体康健胜比年轻人,从来少病的记忆不符……心里算算,自大学离开父母身边,忽忽然已经8年有余了……

昨晚给家里电话,问及母亲银行账户。不能陪在父母身边孝顺,只能以微薄之资聊表心意。很少遇到父亲先接电话,问及身体状况,我的语气故作正经状,严厉“批评”了几句,劝他多出去运动,不要老是呆在家里。父亲只是笑呵呵的感谢我关心,然后和母亲说了几句,千万叮咛……最后末了,电话那头似乎还传来父亲的笑声。

父亲还是和以前一样豁达乐观,微微的笑,我心里这样想着……

清晨,难得很早就醒来,躺在床上,视线指向窗外,天气阴阴的,今天又是一个没有阳光的日子……

胡思乱想,思绪回到昨晚的电话……不知不觉中我的生命已经过去27个年头,父母都已不再是以往了……

想到母亲说起父亲身体患病的话,懞懞中似乎看见父亲的病容……蓦的,跳出来一个画面,父亲的眼睛,透过玻璃从镶着框的的黑白相片中看着我,慈祥的温暖的,那伴随我二十多年生命岁月目光啊……

…………

一阵撕裂的痛楚从我身体某个莫可名状的部位突然炸开来,身体不堪承受的激促的颤动着,卷缩在一起,视线变得昏暗起来,空气被莫名的压力迫离我的周围,被我揉碎变形的枕头里传出沉闷粗重的鼻吸声音,痛苦的酸涩袭偏我的全身……

良久,泪水从眼眶里溢出,浸湿了枕头……

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组件
过于快速的东西总是不太稳妥的,在稳定性和性能上会损失一些,不过这个例子可以初步了解一下如何封装一个简单的组件.

大数据量下的分页
两种大数据量分页方法,具有参考价值,或者直接照搬也不错啊 :D

使用NUnit在.Net编程中进行单元测试
不错的文章,以前没做过NUnit的单元测试,要试试.

利用数据库模版创建方便部署的.Net项目调试环境
数据库部署,以前没这么做过,要试试!

还有很多,慢慢看.

MVP专栏作家列表

社区成员原创文章

思维陷阱

星期二, 03月 30th, 2004

在网上看到一个测验,名字叫《你的决定灭了谁》。

测试是这样的

问题一:如果你知道有一个女人怀孕了,她已经生了八个小孩,其中有三个耳朵聋,两个眼睛瞎,一个智能不足,而这女人自己又有梅毒,请问,你会建议她堕胎吗?

问题二:现在要选举一名领袖,而你这一票很关键。下面是关于这三位候选人的一些事实:

候选人A:跟一些不诚实的政客有往来,而且会咨询占星学家。他有婚外情,是一个老烟枪,每天喝8-10杯的马丁尼。
候选人B:他过去有两次被解雇的记录,睡觉睡到中午才起来,大学时吸过鸦片,而且每天傍晚会喝一夸特的威士忌。
候选人C:他是一位受勋的战争英雄,素食主义者,不抽烟,只偶尔喝一点啤酒。从没有发生过婚外情。

请问你会在这些候选人中选哪一个?

问题2中:
候选人A是 富兰克林﹒罗斯福
候选人B是 温斯顿﹒丘吉尔
候选人C是 亚道夫﹒希特勒。

问题1中:那个正在孕育中的人是贝多芬

——————————————————–

大多数人都作了正常也让人惊奇的回答,选择了希特勒,灭了贝多芬。

意外之余,总结说:不要用既定的价值观来思考事物。

问题很有意思,结论似乎也没有错,不过我看过以后直觉上的反应就是哪儿没对劲……

这种对待事物的看法过于异样了,如果将其类比到生活中作为思维的指标,未免就痛苦了点,其中恐怕还有些自虐的倾向。

如果说异样和痛苦还可以接受,那自虐可就让人十分不爽了……

一个测试的答案无非两种,要么正确要么错误。从这个测试看来,要作出正确的选择,那么我们必须具备对上帝无所不及的伟大仁爱的执著(偏执?),允许这个孕育中的生命诞生;然后要有……要有什么才能选择A和B呢? 除非上帝的无边神威能够探测人心、预测未来,否则即使是上帝也难以作出这样的选择吧?

这个测试竟然连上帝也难以通过,究竟她具有怎样的奥妙呢?

仔细审视,整个命题实际上是在预知了结果的前提下,然后从结果之前特意撷取了几个剥离破碎的片断拼凑在一起,对被测者设下了巧妙的陷阱,使你不得不落入其中。

预知结果——正是如上帝神威也难以具备的能力。

在现实的生活中,我们是无法具备这种能力的,所以我们也只能以正常的观念和逻辑来看待事物,我们仍然希望孩子能够不抽烟少喝酒没有婚外情并且能够成为丘吉尔、罗斯福,希望母亲健康、家庭幸福并且能生下贝多芬,希望大学生能够认真读完大学并且能够成为比尔盖茨。

反过来说,罗斯福再风流相信也不会赞美婚外情,丘吉尔相信仍然会希望他的后代儿女能够“早起早睡身体好”,贝多芬的母亲即使再以自己儿子为荣,也不会认为贝多芬的成就是自己遗传使他耳朵变聋或者梅毒的功劳吧?即使身受者本人也弃自己以往之堕落如履,我们又有什么理由要把他捡起来呢?

事情本身是有些意思的,结论本身也很有蕴意,但是从事情到结论的过程就不是那么回事了。

生活中往往存在这种陷阱,文字上的东西尤其如此。

偶闻徐志摩

星期三, 03月 17th, 2004

真爱不是罪……

我之甘冒世之不韪,竭全力以争者,非特求免凶残之痛苦,实求良善之安顿,求人格之确立,求灵魂之救度耳。

我将于茫茫人海中,访我唯一灵魂之伴侣。

得之,我幸;不得,我命。

今天在网上看到上面的话,其蕴含之深情激越深深地震撼了我……

17 of 18«first...1415161718