[转载]C#.NET发EMAIL的几种方法 MailMessage/SmtpClient/CDO.Message

mikel阅读(883)

[转载]C#.NET发EMAIL的几种方法 MailMessage/SmtpClient/CDO.Message – 熊哥 – 博客园.

C#.NET发EMAIL的几种方法 MailMessage/SmtpClient/CDO.Message

源代码如下:

using System; using System.Collections.Generic; using System.Text; using System.Web; using System.Net.Mail; using System.Net; namespace Pub.Class { /// <summary> /// 发送Email类 /// </summary> public class Email { #region 私有成员 private static object lockHelper = new object(); private string _From; private string _FromEmail; private string _Subject; private string _Body; private string _SmtpServer; private string _SmtpPort = "25"; private string _SmtpUserName; private string _SmtpPassword; private System.Web.Mail.MailFormat _Format = System.Web.Mail.MailFormat.Html; private System.Text.Encoding _Encoding = System.Text.Encoding.Default; #endregion #region 属性 /// <summary> /// 正文内容类型 /// </summary> public System.Web.Mail.MailFormat Format { set { _Format = value; } } /// <summary> /// 正文内容编码 /// </summary> public System.Text.Encoding Encoding { set { _Encoding = value; } } /// <summary> /// FromEmail 发送方地址(如test@163.com) /// </summary> public string FromEmail { set { _FromEmail = value; } } /// <summary> /// From /// </summary> public string From { set { _From = value; } } /// <summary> /// 主题 /// </summary> public string Subject { set { _Subject = value; } } /// <summary> /// 内容 /// </summary> public string Body { set { _Body = value; } } /// <summary> /// SmtpServer /// </summary> public string SmtpServer { set { _SmtpServer = value; } } /// <summary> /// SmtpPort /// </summary> public string SmtpPort { set { _SmtpPort = value; } } /// <summary> /// SmtpUserName /// </summary> public string SmtpUserName { set { _SmtpUserName = value; } } /// <summary> /// SmtpPassword /// </summary> public string SmtpPassword { set { _SmtpPassword = value; } } #endregion #region 构造器 /// <summary> /// 构造器 /// </summary> public Email() { } #endregion #region Send /// <summary> /// 发送EMAIL /// </summary> /// <example> /// <code> /// Email _Email = new Email(); /// _Email.FromEmail = "test@163.com"; /// _Email.Subject = "&lt;div>aaaa&lt;/div>"; /// _Email.Body = "aaaaaaaaaaaaa"; /// _Email.SmtpServer = "smtp.163.com"; /// _Email.SmtpUserName = "aaa"; /// _Email.SmtpPassword = "aaa"; /// _Email.Send("test@163.com"); /// </code> /// </example> /// <param name="toEmail">收信人 接收方地址</param> /// <returns>成功否</returns> public bool SmtpMailSend(string toEmail) { lock (lockHelper) { System.Web.Mail.MailMessage msg = new System.Web.Mail.MailMessage(); try { msg.From = _FromEmail;//发送方地址(如test@163.com) msg.To = toEmail;//接收方地址 msg.BodyFormat = _Format;//正文内容类型 msg.BodyEncoding = _Encoding;//正文内容编码 msg.Subject = _Subject;//主题 msg.Body = _Body;//内容 msg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", "1");//设置为需要用户验证 if (!_SmtpPort.Equals("25")) msg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserverport", _SmtpPort);//设置端口 msg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername", _SmtpUserName);//设置验证用户名 msg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword", _SmtpPassword);//设置验证密码 System.Web.Mail.SmtpMail.SmtpServer = _SmtpServer;//邮件服务器地址(如smtp.163.com) System.Web.Mail.SmtpMail.Send(msg);//发送 return true; } catch { } finally { } } return false; } /// <summary> /// 发送EMAIL /// </summary> /// <param name="toEmail">Email</param> /// <returns>是否成功</returns> public bool CDOMessageSend(string toEmail) { lock (lockHelper) { CDO.Message objMail = new CDO.Message(); try { objMail.To = toEmail; objMail.From = _FromEmail; objMail.Subject = _Subject; if (_Format.Equals(System.Web.Mail.MailFormat.Html)) objMail.HTMLBody = _Body; else objMail.TextBody = _Body; //if (!_SmtpPort.Equals("25")) objMail.Configuration.Fields["http://schemas.microsoft.com/cdo/configuration/smtpserverport"].Value = _SmtpPort; //设置端口 objMail.Configuration.Fields["http://schemas.microsoft.com/cdo/configuration/smtpserver"].Value = _SmtpServer; objMail.Configuration.Fields["http://schemas.microsoft.com/cdo/configuration/sendusing"].Value = 1; objMail.Configuration.Fields["http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout"].Value = 10; objMail.Configuration.Fields.Update(); objMail.Send(); return true; } catch {} finally{ } System.Runtime.InteropServices.Marshal.ReleaseComObject(objMail); objMail = null; } return false; } /// <summary> /// CDOMessageSend /// </summary> /// <param name="toEmail"></param> /// <param name="sendusing"></param> /// <returns></returns> public bool CDOMessageSend(string toEmail,int sendusing) { lock (lockHelper) { CDO.Message objMail = new CDO.Message(); try { objMail.To = toEmail; objMail.From = _FromEmail; objMail.Subject = _Subject; if (_Format.Equals(System.Web.Mail.MailFormat.Html)) objMail.HTMLBody = _Body; else objMail.TextBody = _Body; if (!_SmtpPort.Equals("25")) objMail.Configuration.Fields["http://schemas.microsoft.com/cdo/configuration/smtpserverport"].Value = _SmtpPort; //设置端口 objMail.Configuration.Fields["http://schemas.microsoft.com/cdo/configuration/smtpserver"].Value = _SmtpServer; objMail.Configuration.Fields["http://schemas.microsoft.com/cdo/configuration/sendusing"].Value = sendusing; objMail.Configuration.Fields["http://schemas.microsoft.com/cdo/configuration/sendemailaddress"].Value = _FromEmail; objMail.Configuration.Fields["http://schemas.microsoft.com/cdo/configuration/smtpuserreplyemailaddress"].Value = _FromEmail; objMail.Configuration.Fields["http://schemas.microsoft.com/cdo/configuration/smtpaccountname"].Value = _SmtpUserName; objMail.Configuration.Fields["http://schemas.microsoft.com/cdo/configuration/sendusername"].Value = _SmtpUserName; objMail.Configuration.Fields["http://schemas.microsoft.com/cdo/configuration/sendpassword"].Value = _SmtpPassword; objMail.Configuration.Fields["http://schemas.microsoft.com/cdo/configuration/smtpauthenticate"].Value=1; objMail.Configuration.Fields.Update(); objMail.Send(); return true; } catch { } finally{ } System.Runtime.InteropServices.Marshal.ReleaseComObject(objMail); objMail = null; } return false; } /// <summary> /// SmtpClientSend /// </summary> /// <param name="toEmail"></param> /// <returns></returns> public bool SmtpClientSend(string toEmail) { lock (lockHelper) { System.Net.Mail.MailMessage message = new MailMessage(_FromEmail, toEmail, _Subject, _Body); message.SubjectEncoding = _Encoding; message.BodyEncoding = _Encoding; message.IsBodyHtml = true; message.Priority = MailPriority.High; SmtpClient client = new SmtpClient(_SmtpServer); client.UseDefaultCredentials = false; client.Credentials = new NetworkCredential(_SmtpUserName, _SmtpPassword); client.DeliveryMethod = SmtpDeliveryMethod.Network; client.Port = Str.ToInt(_SmtpPort, 587); client.EnableSsl = true; try { client.Send(message); } catch { return false; } return true; } } #endregion } }

多线程服务调用:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Configuration.Install; using System.ServiceProcess; using System.Collections; using System.Threading; using System.Xml; using System.IO; using System.Net.Mail; using System.Runtime.Remoting.Channels.Tcp; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting; using Pub.Class; using System.Diagnostics; namespace MailService { [RunInstaller(true)] public partial class MService : ServiceBase { public static bool isRun = false; public Queue emailQueue = new Queue(); private Thread readEmailThread; private Thread[] sendEmailThread; private string[] strList = new string[] { "MailService 启动成功!", "MailService 停止!", "{2} {1} - [{0}] - 发送失败!", "{2} {1} - [{0}] - 发送成功!", "LiveRemotingService 已启动,服务端口6669。", "LiveRemotingService 停止!" }; private struct Config { public string Conn; public string LogFile; public string SmtpServer; public string UserName; public string Password; public string FromAddress; public int AmountThread; public int RecordCount; public int TimeInterval; } private Config config = new Config(); public MService() { System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false; InitializeComponent(); if (!System.Diagnostics.EventLog.SourceExists("MailSource")) System.Diagnostics.EventLog.CreateEventSource("MailSource", "MailServiceLog"); this.eventLog1.Source = "MailSource"; this.eventLog1.Log = "MailServiceLog"; this.eventLog2.Source = "LiveRemotingSource"; this.eventLog2.Log = "MailServiceLog"; } protected override void OnStart(string[] args) { try { InitConfig(); this.eventLog1.WriteEntry(strList[0], System.Diagnostics.EventLogEntryType.SuccessAudit); this.timer1.Interval = config.TimeInterval * 1000; this.timer1.Enabled = true; sendEmailThread = new Thread[config.AmountThread]; } catch (Exception e) { this.eventLog1.WriteEntry(e.ToString(), System.Diagnostics.EventLogEntryType.Error); } } protected override void OnStop() { this.eventLog1.WriteEntry(strList[1], System.Diagnostics.EventLogEntryType.SuccessAudit); GC.Collect(); this.timer1.Enabled = false; } private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { if (isRun) return; timer1.Enabled = false; readEmailThread = new Thread(new ThreadStart(ReadEmailQuque)); readEmailThread.IsBackground = true; readEmailThread.Start(); } private void InitConfig(){ config.Conn = Pub.Class.WebConfig.GetApp("ConnString"); config.LogFile = Pub.Class.WebConfig.GetApp("logFile"); config.SmtpServer = Pub.Class.WebConfig.GetApp("SmtpServer"); config.UserName = Pub.Class.WebConfig.GetApp("UserName"); config.Password = Pub.Class.WebConfig.GetApp("Password"); config.FromAddress = Pub.Class.WebConfig.GetApp("FromAddress"); string amountThread = Pub.Class.WebConfig.GetApp("AmountThread"); config.AmountThread = amountThread.Equals("") ? 1 : Convert.ToInt32(amountThread); config.AmountThread = config.AmountThread < 1 ? 1 : config.AmountThread; string recordCount = Pub.Class.WebConfig.GetApp("RecordCount"); config.RecordCount = recordCount.Equals("") ? 1000 : Convert.ToInt32(recordCount); config.RecordCount = config.RecordCount < 1000 ? 1000 : config.RecordCount; string timeInterval = Pub.Class.WebConfig.GetApp("TimeInterval"); config.TimeInterval = timeInterval.Equals("") ? 1000 : Convert.ToInt32(timeInterval); config.TimeInterval = config.TimeInterval < 2 ? 2 : config.TimeInterval; } private void ReadEmailQuque(){ timer1.Enabled = true; IList<EC_EmailList> list = EC_EmailListFactory.Instance().SelectListByTop(config.RecordCount); if (list.Count == 0) return; isRun = true; for (int i = 0; i < list.Count; i++) { emailQueue.Enqueue(list[i]); } for (int i = 0; i < config.AmountThread; i++) { sendEmailThread[i] = new Thread(new ThreadStart(DoSendEmail)); sendEmailThread[i].Name = "Thread" + (i+1).ToString(); sendEmailThread[i].Start(); } list = null; } private void DoSendEmail(){ while (true) { EC_EmailList objMail; lock(this){ if (emailQueue.Count>0) { objMail = (EC_EmailList)emailQueue.Dequeue(); } else { isRun = false; return; } } int mailID = (int)objMail.EmailID; string strTo = objMail.To; string strSubject = objMail.Subject; string strBody = objMail.Body; string strFrom = objMail.From; string smtpServer = objMail.SmtpServer; string userName = objMail.UserName; string password = objMail.Password; bool isTrue = SendMail(strTo, strSubject, strBody, strFrom, smtpServer, userName, password, ""); EC_EmailListFactory.Instance().DeleteByID(mailID); } } public bool SendMail(string strTo, string strSubject, string strBody, string strFrom, string smtpServer, string userName, string password, string attachments) { Email email = new Email(); string strSmtpServer = smtpServer.Length > 0 ? smtpServer : config.SmtpServer.Trim(); email.SmtpServer = strSmtpServer; email.SmtpUserName = userName.Length > 0 ? userName : config.UserName.Trim(); email.SmtpPassword = password.Length > 0 ? password : config.Password.Trim(); email.SmtpPort = strSmtpServer.ToLower().Contains("gmail") ? "587" : "25"; email.EnableSsl = strSmtpServer.ToLower().Contains("gmail") ? true : false; email.FromEmail = strFrom.Length > 0 ? strFrom : config.FromAddress.Trim(); email.Subject = strSubject; email.Body = strBody; email.Encoding = System.Text.Encoding.UTF8; bool isSuccess = email.SmtpClientSend(strTo); return isSuccess; } public void ErrorLog(string strMessage) { lock(this){ StreamWriter sw = new StreamWriter(config.LogFile + "MailLog.txt", true); sw.WriteLine(strMessage); sw.Flush(); sw.Close(); } } } }

曾经运行在MSN的MCLUB的服务器上跑发EMAIL的服务。应该是安全无死锁调用。

[转载]Asp.net MVC2使用第三方控件

mikel阅读(1052)

[转载]Asp.net MVC2使用第三方控件 – 海纳百川 – 博客园.

ASP.NET MVC框架提供了大量的HTML渲染的方法和控件,但是使用起来有诸多的不便。对于有经验的设计者使用HTML helpers可以构建一个简单的用户界面,然后加上一些HTML和css就能构建出非常漂亮的界面。但是,对开发人员来说使用一些第三方的控件,界面可 能更加方便,开发效率会更高,也使开发人员不用花大量的时间在UI界面上。

这篇文章将介绍两个非常有用的,可以在ASP.NET mvc 2中使用的第三方的控件:MvcContrib GridSlickUpload。文章将以 例子的形式进行说明。

MvcContrib Grid

Gird在现在的应用系统中随处可见。MvcContrib Grid是一个开源的控件,可以构建很整洁的HTML的表格。一般在ASP.NET MVC开发中,你可以使用下面代码产生一个表格。

<table>
<tr>
<th>Username</th>
<th>First name</th>
<th>Last name</th>
<th>Email</th>
<th>&nbsp;</th>
</tr>
<% foreach (var profile in Model) { %>
<tr>
<td>
<%= Html.Encode(profile.Username) %>
</td>
<td>
<%= Html.Encode(profile.FirstName) %>
</td>
<td>
<%= Html.Encode(profile.LastName) %>
</td>
<td>
<%= Html.Encode(profile.Email) %>
</td>
<td>
<%= Html.ActionLink("View", "Show",
new{username = profile.Username}) %>
</td>
</tr>
<% } %>
</table>

从上面的代码可以看出,写MVC的View和写Asp代码一样,一行一行的输出,非常的麻烦。使用MvcContrib Grid,只需一行代码,如下:

<%= Html.Grid(Model).AutoGenerateColumns() %>

这行代码将会把实体类所以的属性列出来。但是有些字段是不需要显示的,我们可以通过下面代码来指定输出列以及输出地格式:

    <h2>产品列表</h2>
   <%= Html.Grid(Model).Columns(column => {
    column.For(x => x.ProductID).Named("Product ID");
column.For(x => x.ProductName);
column.For(x => x.QuantityPerUnit);
column.For(x => x.UnitPrice).Format("{0:N2}");
column.For(x => Html.ActionLink("View Product", "Detail", new { id = x.ProductID })).DoNotEncode();
}) %>

这个例子的数据库是NorthWind,效果如下图:

显示数据库中所有产品分类的名称:

qq1

显示指定分类的所有产品,这块使用了MvcContrib Grid

tty

显示某个产品的详细信息:

qq3

上面的代码就指定输出列。格式化金额字段。更多关于此控件的用法可以查看:http://www.jeremyskinner.co.uk.。

SlickUpload

下面介绍一下在ASP.NET MVC中使用SlickUploadSlickUpload,估计很多童 鞋都有使用过。它有下面这些好处:

1、ASP.NET中上传文件的时候会把上传的文件全部加载到服务器内存中,而SlickUpload直接把上传文件流写入硬盘或数据库。
2、 上传进度条能够实时显示文件上传的进度状态。
3、SlickUpload高度的可自定义性,可以允许我们在上传过程中加入其它的业务逻辑
4、 支持web farm和web garden

在asp.net mvc中使用SlickUpload和 asp.net中类似。

1、在asp.net mvc2项目中添加Krystalware.SlickUpload引用。

2、配置web.config:

在configuration节点中添加下面配置:

    <configSections>
        <sectionGroup name="slickUpload" type="Krystalware.SlickUpload.Configuration.NameValueConfigurationSectionHandler, Krystalware.SlickUpload">
            <section name="uploadParser" type="Krystalware.SlickUpload.Configuration.NameValueConfigurationSectionHandler, Krystalware.SlickUpload"/>
            <section name="uploadStreamProvider" type="Krystalware.SlickUpload.Configuration.NameValueConfigurationSectionHandler,Krystalware.SlickUpload"/>
            <section name="statusManager" type="Krystalware.SlickUpload.Configuration.StatusManagerConfigurationSectionHandler,Krystalware.SlickUpload"/>
        </sectionGroup>
    </configSections>

    <location path="">
        <slickUpload>
            <uploadParser handleRequests="true" />
            <uploadStreamProvider provider="File" location="~/Files/"  existingAction="Overwrite" />

        </slickUpload>
        <system.web>
            <httpRuntime maxRequestLength="1048576"
            executionTimeout="300"/>
        </system.web>
        <system.webServer>
            <security>
                <requestFiltering>
                    <requestLimits maxAllowedContentLength="2072576000"/>
                </requestFiltering>
            </security>
        </system.webServer>
    </location>

在system.web中添加下面配置

      <httpHandlers>
          <add path="SlickUpload.axd" verb="GET,HEAD,POST,DEBUG" type="Krystalware.SlickUpload.SlickUploadHandler,Krystalware.SlickUpload" />
      </httpHandlers>

      <httpModules>
          <add name="HttpUploadModule" type="Krystalware.SlickUpload.HttpUploadModule,Krystalware.SlickUpload"/>
      </httpModules>

3、在试图中引入此控件和其命名空间:

<%@ Import Namespace="Krystalware.SlickUpload"%>
<%@ Register Assembly="Krystalware.SlickUpload" Namespace="Krystalware.SlickUpload.Controls" TagPrefix="kw" %>

4、这个例子的控制器代码如下:

public class UploadController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult UploadResult()
    {
        UploadStatus status = UploadConnector.GetUploadStatus();
        return View(status.GetUploadedFiles());
    }
}

4、使用Html.BeginForm创建一个表单,在此表单上使用此控件,代码如下:

<% using (Html.BeginForm(
"UploadResult",
"Upload",
FormMethod.Post,
new {
id = "uploadForm",
enctype = "multipart/form-data"
})) { 
 %>
<kw:slickupload ID="SlickUpload1" runat="server" UploadFormId="uploadForm" MaxFiles="1" ShowDuringUploadElements="cancelButton" HideDuringUploadElements="uploadButton" >
<DownlevelSelectorTemplate>
<input type="file" />
</DownlevelSelectorTemplate>
<UplevelSelectorTemplate>
<input type="button" value="Add File" />
</UplevelSelectorTemplate>
<FileTemplate>
<kw:FileListRemoveLink ID="FileListRemoveLink1" runat="server">
[x] remove</kw:FileListRemoveLink>
<kw:FileListFileName ID="FileListFileName1" runat="server" />
<kw:FileListValidationMessage ID="FileListValidationMessage1" runat="server" ForeColor="Red" />
</FileTemplate>
<ProgressTemplate>
<table width="99%"><tr><td>
<p>Upload Progress:</p>
<div class="progressBorder">
<kw:UploadProgressBarElement ID="UploadProgressBarElement1" runat="server"
CssClass="progressBar"/>
<div class="progressValue">
<kw:UploadProgressElement ID="UploadProgressElement1" runat="server"
Element="PercentCompleteText">
(calculating)
</kw:UploadProgressElement>
</div>
</div>
</td></tr></table>
</ProgressTemplate>
</kw:slickupload>
<hr />
<p>
<input type="submit" value="Upload"
id="uploadButton" />
</p>
<% } %>

用UploadResult的View显示结果,使用MvcContrib Grid来显示:

   <%= Html.Grid(Model).Columns(column => {
    column.For(x => x.ClientName);
    column.For(x => x.ContentType);
    column.For(x => x.ContentLength);
}) %>

上传页面:

hhh

选择上传文件:

vvv

上传结果:

ggg

总结:这篇文章介绍了两个第三方控件在ASP.net MVC2中的使用。

参考Asp.net  mvc2 in action

代码:http://cid-aef1e64945224a20.office.live.com/browse.aspx/.Public?uc=1

作者:朱祁林
出处:http://zhuqil.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

[转载]C# string 和 stringbuilder的区别

mikel阅读(873)

[转载]C# string 和 stringbuilder的区别 – ※森林小居※ – 博客园.

String 对象是不可改变的。每次使用 String 类中的方法之一或进行运算时(如赋值、拼接等)时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间。而 StringBuilder 则不会,在需要对字符串执行重复修改的情况下,与创建新的 String 对象相关的系统开销可能会非常昂贵。如果要修改字符串而不创建新的对象,则可以使用 System.Text.StringBuilder 类;例如,当在一个循环中将许多字符串连接在一起时,使用 StringBuilder 类可以提升性能。

1、设置容量与长度

StringBuilder   MyStringBuilder   =   new   StringBuilder(“Hello   World!”,   25);   方式1
MyStringBuilder.Capacity   =   25;  方式2
EnsureCapacity   方法可用来检查当前   StringBuilder   的容量。如果容量大于传递的值,则不进行任何更改;但是,如果容量小于传递的值,则会更改当前的容量以使其与传递的值匹配。

也可以查看或设置   Length   属性。如果将   Length   属性设置为大于   Capacity   属性的值,则自动将   Capacity   属性更改为与   Length   属性相同的值。如果将   Length   属性设置为小于当前   StringBuilder   对象内的字符串长度的值,则会缩短该字符串。

2、 修改   StringBuilder   字符串

方法名                                    使用
StringBuilder.Append                将信息追加到当前 StringBuilder 的结尾
StringBuilder.AppendFormat      用带格式文本替换字符串中传递的格式说明符
StringBuilder.Insert                   将字符串或对象插入到当前 StringBuilder 对象的指定索引处
StringBuilder.Remove                从当前 StringBuilder 对象中移除指定数量的字符
StringBuilder.Replace                 替换指定索引处的指定字符

Append
Append 方法可用来将文本或对象的字符串表示形式添加到由当前 StringBuilder 对象表示的字符串的结尾处。下面的示例将一个 StringBuilder 对象初始化为“Hello World”,然后将一些文本追加到该对象的结尾处。将根据需要自动分配空间。

C# ]
StringBuilder MyStringBuilder = new StringBuilder(“Hello World!”);
MyStringBuilder.Append(” What a beautiful day.”);
Console.WriteLine(MyStringBuilder);

此 示例将 Hello World! What a beautiful day. 显示到控制台。

AppendFormat
AppendFormat 方法将文本添加到 StringBuilder 的末尾,而且实现了 IFormattable 接口,因此可接受格式化部分中描述的标准格式字符串。可以使用此方法来自定义变量的格式并将这些值追加到 StringBuilder 的后面。下面的示例使用 AppendFormat 方法,将一个设置为货币值格式的整数值放到 StringBuilder 的末尾。

C# ]
int MyInt = 25;
StringBuilder MyStringBuilder = new StringBuilder(“Your total is “);
MyStringBuilder.AppendFormat(“{0:C} “, MyInt);
Console.WriteLine(MyStringBuilder);

此示例将 Your total is $25.00 显示到控制台。

Insert
Insert 方法将字符串或对象添加到当前 StringBuilder 中的指定位置。下面的示例使用此方法将一个单词插入到 StringBuilder 的第六个位置。

[  C# ]
StringBuilder MyStringBuilder = new StringBuilder(“Hello World!”);
MyStringBuilder.Insert(6,”Beautiful “);
Console.WriteLine(MyStringBuilder);

此 示例将 Hello Beautiful World! 显示到控制台。

Remove
可以使用 Remove 方法从当前 StringBuilder 中移除指定数量的字符,移除过程从指定的从零开始的索引处开始。下面的示例使用 Remove 方法缩短 StringBuilder。

[  C# ]
StringBuilder MyStringBuilder = new StringBuilder(“Hello World!”);
MyStringBuilder.Remove(5,7);
Console.WriteLine(MyStringBuilder);

此示例将 Hello 显示到控制台。

Replace使用 Replace 方法,可以用另一个指定的字符来替换 StringBuilder 对象内的字符。下面的示例使用 Replace 方法来搜索 StringBuilder 对象,查找所有的感叹号字符 (!),并用问号字符 (?) 来替换它们。

[  C# ]
StringBuilder MyStringBuilder = new StringBuilder(“Hello World!”);
MyStringBuilder.Replace(‘!’, ‘?’);
Console.WriteLine(MyStringBuilder);

此示例将 Hello World? 显示到控制台。

3、将Stringbuilder串转换为string形式

string = StringBuilder.toString();

[转载]轻松简单搭建Linux下的C#开发环境

mikel阅读(1157)

[转载]轻松简单搭建Linux下的C#开发环境 – 河马流星拳 – 博客园.

先看看本篇文章最终效果:在 Ubuntu 里跑的开 发环境 MonoDevelop


[图 片:MonoDevelop1.png]

如 果平时主要开发控制台类、组件、后端服务等程序,可以尝试在Linux类操作系统下搭建C#.Net开发环境,好处是在Linux环境里你不用担心朋友或 同事拿你的电脑来玩魔兽世界或者一不小心被装了一大堆流氓软件 😉

1、Linux发行版的选择

在Linuxux操作系统里只要安装Mono环 境就可以开发C#程序,Linux的众多发行版RedHat/CentOS/Fedora、OpenSuse、Debian、Ubuntu都可以安装 Mono。
鉴于 目前 Ubuntu 容易安装、界面漂亮而且比较多人用作桌面环境,所以这里推荐使用 Ubuntu 10.04 。官方网站是:http://www.ubuntu.com/
在官方网站下载回来的是一个光盘映像文件 (ISO格式),这里需要注意的是 Ubuntu 共有4个不同版本的ISO文件:Desktop版、Alternative版、Netbook版、 Server版。一般下载Desktop就可以了。如果你想通过网络启动安装程序或者使用硬盘安装则需要下载Alternative版。
如果你的电脑硬件配置比较低(内存少于等于 512MB),还可以下载一个轻量级的衍生版:Xubuntu(http://www.xubuntu.org/),如果你的电脑只有256MB内存,那还可以 下载另一个衍生版Lubuntu(http://lubuntu.net/),这个更加轻量级,平时系统启动后只占用 70~100MB内存。

2、安装Ubuntu

安装Ubuntu 的方法非常简单,跟装 WinXP差不多,只需点5,6次“下一步”过10来分钟就可以完成。因为关于安装Ubuntu的过程已经有大量的文章介绍,这里就不再赘述了,下面主要 列举一下安装方式,大家可以根据自己的具体情况选择合适的:

(1)虚拟机安装
如果你的电脑速度飞快,内存比较大,用这种方式 安装最快,虚拟机软件推荐使用免费 的 VirtualBox。先装好虚拟机软件,然后创建一个新的虚拟机,把下载回来的 ISO文件挂靠到虚拟机,启动之后就可以安装了。

(2)尝试性安装
如果你仅仅想尝试一下在Linux环境开发C# 的感觉,并不打算长期使用,则可以使用这种安装模式。这种安装模式不需要调整硬盘分区(因为整个Linux将安装到一个“虚拟硬盘”文件里头)、不会弄坏 你的现有的系统和软件,只是性能会稍微减低一些。
首先你的系统必须是WinXP/Vista /Win7,然后把ISO文件和一个 Wubi Installer (http://wubi-installer.org/) 的软件放在同一个目录,运行 Wubi installer,选择Ubuntu的安装位置,然后就开始复制文件了,重启计算机会多出一项启动项“Ubuntu install”,选择 它就开始真正的安装过程了。

下 面的安装方式需要先在硬盘腾出一块空白的空间(最好准备至少10GB),主分区以外的自由空间或者扩展分区的自由空间都可以,你可以用 PQMagic软件慢慢 调整自己硬盘的分区大小。在安装过程中程序会询问你将Ubuntu安装在何处,选择使用“最大连续空间”即可。

(3)光盘安装
这种安装方式最简单,将下载回来的ISO文件刻 录成光盘,设置从光盘启动并重启计算机。

(4) 硬盘安装
要下载Alternative版的ISO文件, 放到C盘根目录,然后下载“UNetbootin
”(http://unetbootin.sourceforge.net/)软件,也放在C盘根目录,运 行 UNetbootin,在发行版类型项选择Ubuntu和MediaHD即开始复制文件,重启电脑开始安装。

(5)用U盘安装/安装到U盘
先使用安装光盘启动计算机,选择“试用”进入 LiveCD模式的Ubuntu,然后在“系统”->“系统管理”点击“制作启动盘”,准备一个1GB以上的U盘,启动盘制作程序会把Ubuntu 的所有文件复制到U盘,然后就可以使用这个U盘启动其他电脑并安装系统了。也可以直接从这个U盘启动进入系统。

(6)通过网络安装
如果你的电脑没有光驱也不支持U盘启动,而带有 从网卡启动(PXE)功能。或者有一批电脑需要批量安装,则可以使用这种安装模式,具体的请见:http://kalashnicov.javaeye.com/blog/663337

3、安装开发环境 MonoDevelop

安装好Ubuntu 10.04之后会发现系统已经自带Mono运行和编译环境,而且还有部分Ubuntu系统自带的软件是C#写的,比如tomboy便利帖、IQ测试游戏 gbrainy、照片查看和管理程序F-Spot

[图片:F-spot.png]

如果你已经习惯了Win7的任 务栏,推荐另外一 个任务栏软件“Docky”,它也是C#写的

[图片:Docky.png]

MacOS的同学请淡定。
记住在Ubuntu里安装软件是不需要去什么软 件下载网站的,所有需要的软件都可以在“Ubuntu软件中心”找到、安装、卸载。

运行“Ubuntu软件中心”,输入需要安装的 软件名称,比如 “MonoDevelop”,然后点击“安装”,程序会自动上网下载并安装。

好了,现在就已经搭建好C#开发环境了,试试写 一个HelloWorld吧(效果图 片见文章开头处)

4、其他

MonoDevelop除了能 写C#程序之外, 还能写C,C++,Java等程序,只要安装相应的插件和编译器即可,

[图片:MonoDevelop2.png]

附录:

mono项目主页: http://mono-project.com

控制台、窗口、Web的HelloWorld演示程序:http://mono-project.com/Mono_Basics

mono 与 ms.net 的兼容性列表: http://mono-project.com/Compatibility

[转载]使用XML及XSL生成简单HTML

mikel阅读(931)

[转载]使用XML及XSL生成简单HTML – 专注ASP.NET & RIA以及SQLServer BI&GIS – 博客园.

某些时候需要生成HTML展现数据,考虑过XML加XSL方法吗?比如,以html邮件的方式发送一些数据。

本文通过两个已经存在的文件,xml文件和xsl文件演示如何将其转换成HTML。

首先,准备XML文件,这里为了演示,随便定义了一组数据。这些定义好的数据用于后面套入到对应的xsl模板中。

<ROOT>

<ASPNETX Username=dudu City=Shanghai Cool=70 />

<ASPNETX Username=Bill City=Meiguo Cool=100 />

<ASPNETX Username=Gates City=Meiguo Cool=100 />

<ASPNETX Username=Aobama City=Meiguo Cool=80 />

<ASPNETX Username=aspnetx City=Beijing Cool=60 />

<ASPNETX Username=Geo City=USA.East Cool=20 />

<ASPNETX Username=Mike City=USA.West Cool=30 />

<ASPNETX Username=Jim City=Jilin Cool=90 />

<ASPNETX Username=Tim City=Hebei Cool=10 />

<ASPNETX Username=Ada City=Big Apple Cool=10 />

<ASPNETX Username=Jill City=unknown Cool=50 />

</ROOT>

XML数据文件可以自己组织格式,因为在xsl模板中是支持x-path查询的。

然后,准备XSL文件:

<xsl:stylesheet version=1.0 xmlns:xsl=http://www.w3.org/1999/XSL/Transform xmlns:msxsl=urn:schemas-microsoft-com:xslt exclude-result-prefixes=msxsl>

<xsl:output method=html indent=yes/>

<xsl:template match=/>

<table align=left cellpadding=2 cellspacing=5>

<tr>

<td style=font-family: Verdana; font-size: 15px; font-weight: bold;>User in cnblogs:</td>

</tr>

<tr>

<td style=font-family: Verdana; font-size: 10px;>

<table width=500px align=left cellpadding=2 cellspacing=0 style=font-family: Verdana; font-size: 10px;>

<tr>

<td bgcolor=#808080>

<font color=#FFFFFF>

<b>User name</b>

</font>

</td>

<td bgcolor=#808080>

<font color=#FFFFFF>

<b>City</b>

</font>

</td>

<td bgcolor=#808080>

<font color=#FFFFFF>

<b>Cool</b>

</font>

</td>

</tr>

<xsl:for-each select=ROOT/ASPNETX>

<tr>

<td style=border: 1px solid #808080>

<xsl:value-of select=@Username/>

</td>

<td style=border: 1px solid #808080>

<xsl:value-of select=@City/>

</td>

<td style=border: 1px solid #808080>

<xsl:value-of select=@Cool/>

</td>

</tr>

</xsl:for-each>

</table>

</td>

</tr>

</table>

</xsl:template>

</xsl:stylesheet>

在模板文件之中,xsl:template之间就是要展现的html模板的内容。

xsl:value-of对应数据区域,select后跟x-path查询。

Xsl:for-each枚举得到的集合。

通过以上两个标签的占位,xml的数据就会根据其定义出现在对应的位置。

Xml和xsl都准备好,最后,准备C#代码,下面的代码将把模板xsl和数据xml加载进来,然后把html内容输出成一个string字符串:

static void TestXls()

{

//数据文件

XmlReader _xmlxml = XmlReader.Create(“xmldata.xml”);

//模板文件

XmlReader _xmlxsl = XmlReader.Create(“xsldata.xml”);

//实例化转换对象

XslCompiledTransform xslct = new XslCompiledTransform();

xslct.Load(_xmlxsl);

MemoryStream ms = new MemoryStream();

XmlTextWriter xmltxtWr = new XmlTextWriter(ms, null);

//开始转换,并且将结果保存到writer中。

xslct.Transform(_xmlxml, xmltxtWr);

//读取结果

StreamReader st = new StreamReader(ms);

ms.Seek(0, SeekOrigin.Begin);

string TransformedHTML = st.ReadToEnd();

Console.WriteLine(TransformedHTML);

}

在.net下提供了现成的转换对象,XslCompiledTransform。通过Load方法加载xsl文件后,就可以调用Transform 方法对xml进行转换了。

Xmldata.xml和xsldata.xml文件如果在项目中,记得设置其copy to output directory。默认这两个文件是不输出到bin目录的,所以如果不设置会导致程序无法加载到相应的xml和xsl文件。

实际操作的时候,需要自己先组织好html部分的内容,尽量不要用网页设计工具,因为这样会生成很多的垃圾标签,所以最好自己手写。然后在适当的位 置加上<xsl:xxx />标签,最后放到xsl文件中。

做好xsl模板后,建议先自己调试一下看看能否搭配xml正常的输出数据,偶尔有一些不符合规范的地方程序会报错。

Xml的数据最常用的来源就是SQL语句加for xml auto了,此时需要注意模板里的x-path查询也要根据xml结果做相应的变化。

由于visual studio在调试的时候,查看字符串变量支持文本模式和html模式,所以在实际开发的时候调试起来会方便的很多。

需要注意:

模板中不能出现&这样的字符,所以&nbsp;这样的要处理掉。

XML做x-path查询是区分大小写的,比如Root和root是无法匹配上的。

示例项目下载

环境:Visual Studio 2010

[转载]命令模式-1

mikel阅读(917)

[转载]命令模式-1 – 云飞龙行 – 博客园.

命令模式也是开发中常见的一个模式,也不是太难,比较简单,下面来详细的写一下命令模式。

命令模式(Command)

1  场景问题

1.1  如何开机

估计有些朋友看到这个标题会非常奇怪,电脑装配好了,如何开机?不就是按下启动按钮就可以了吗?难道还有什么玄机不成。
对于使用电脑的客户——就是我们来说,开机确实很简单,按下启动按钮,然后耐心等待就可以了。但是当我们按下启动按钮过后呢?谁来处理?如何处理?都经历 了怎样的过程,才让电脑真正的启动起来,供我们使用。
先一起来简单的认识一下电脑的启动过程,了解一下即可。

  • 当我们按下启动按钮,电源开始向主板和其它设备供电
  • 主板的系统BIOS(基本输入输出系统)开始加电后自检
  • 主板的BIOS会依次去寻找显卡等其它设备的BIOS,并让它们自检或者初始化
  • 开始检测CPU、内存、硬盘、光驱、串口、并口、软驱、即插即用设备等等
  • BIOS更新ESCD(扩展系统配置数据),ESCD是BIOS和操作系统交换硬件配置数据的一种手段
  • 等前面的事情都完成后,BIOS才按照用户的配置进行系统引导,进入操作系统里面,等到操作系统装载并初始化完毕,就出现我们熟悉的系统登录界面 了。

1.2  与我何干

讲了一通电脑启动的过程,有些朋友会想,这与我何干呢?
没错,看起来这些硬件知识跟你没有什么大的关系,但是,如果现在提出一个要求:请你用软件把上面的过程表现出来,你该如何实现?
首先把上面的过程总结一下,主要就这么几个步骤:首先加载电源,然后是设备检查,再然后是装载系统,最后电脑就正常启动了。可是谁来完成这些过程?如何完 成?
不能让使用电脑的客户——就是我们来做这些工作吧,真正完成这些工作的是主板,那么客户和主板如何发生联系呢?现实中,是用连接线把按钮连接到主板上的, 这样当客户按下按钮的时候,就相当于发命令给主板,让主板去完成后续的工作。
另外,从客户的角度来看,开机就是按下按钮,不管什么样的主板都是一样的,也就是说,客户只管发出命令,谁接收命令,谁实现命令,如何实现,客户是不关心 的。

1.3  有何问题

把上面的问题抽象描述一下:客户端只是想要发出命令或者请求,不关心请求的真正接收者是谁,也不关心具体如何实现,而且同一个请求的动作可以有不同的请求 内容,当然具体的处理功能也不一样,请问该怎么实现?

2  解决方案

2.1  命令模式来解决

用来解决上述问题的一个合理的解决方案就是命令模式。那么什么是命令模式呢?
(1)命令模式定义
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

(2)应用命令模式来解决的思路
首先来看看实际电脑的解决方案
先画个图来描述一下,看看实际的电脑是如何处理上面描述的这个问题的,如图1所示:

图 1  电脑操作示意图

当客户按下按钮的时候,按钮本身并不知道如何处理,于是通过连接线来请求主板,让主板去完成真正启动机器的功能。
这里为了描述它们之间的关系,把主板画到了机箱的外面。如果连接线连接到不同的主板,那么真正执行按钮请求的主板也就不同了,而客户是不知道这些变化的。
通过引入按钮和连接线,来让发出命令的客户和命令的真正实现者——主板完全解耦,客户操作的始终是按钮,按钮后面的事情客户就统统不管了。
要用程序来解决上面提出的问题,一种自然的方案就是来模拟上述解决思路。
在命令模式中,会定义一个命令的接口,用来约束所有的命令对象,然后提供具体的命令实现,每个命令实现对象是对客户端某个请求的封装,对应于机箱上的按 钮,一个机箱上可以有很多按钮,也就相当于会有多个具体的命令实现对象。
在命令模式中,命令对象并不知道如何处理命令,会有相应的接收者对象来真正执行命令。就像电脑的例子,机箱上的按钮并不知道如何处理功能,而是把这个请求 转发给主板,由主板来执行真正的功能,这个主板就相当于命令模式的接收者。
在命令模式中,命令对象和接收者对象的关系,并不是与 生俱来的,需要有一个装配的过程,命令模式中的Client对象就来实现这样的功能。这就相当于在电脑的例子中,有了机箱上的按钮,也有了主板,还需要有 一个连接线把这个按钮连接到主板上才行。
命令模式还会提供一个Invoker对象来持有命令对象,就像电脑的例子,机箱上会有多个按钮,这个机箱就相当于命令模式的Invoker对象。这样一 来,命令模式的客户端就可以通过Invoker来触发并要求执行相应的命令了,这也相当于真正的客户是按下机箱上的按钮来操作电脑一样。

2.2  模式结构和说明

命令模式的结构如图2所示:


图2  命令模式结构图
Command:
定义命令的接口,声明执行的方法。
ConcreteCommand:
命令接口实现对象,是“虚”的实现;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
Receiver:
接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。
Invoker:
要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对 象的入口。
Client:
创建具体的命令对象,并且设置命令对象的接收者。注意这个不是我们常规意义上的客户端,而是在组装命令对象和接收者,或许,把这个Client称为装配者 会更好理解,因为真正使用命令的客户端是从Invoker来触发执行。

2.3  命令模式示例代码

(1)先来看看命令接口的定义,示例代码如下:

/**

* 命令接口,声明执行的操作

*/

public interface Command {

/**

* 执行命令对应的操作

*/

public void execute();

}

 (2)再来看看具体的命令实现对象,示例代码如下:
/**  * 具体的命令实现对象  */ public class ConcreteCommand implements Command {     /**      * 持有相应的接收者对象      */     private Receiver receiver = null;     /**      * 示意,命令对象可以有自己的状态      */     private String state;     /**      * 构造方法,传入相应的接收者对象      * @param receiver 相应的接收者对象      */     public ConcreteCommand(Receiver receiver){        this.receiver = receiver;     }       public void execute() {        //通常会转调接收者对象的相应方法,让接收者来真正执行功能        receiver.action();     } }

(3)再来看看接收者对象的实现示意,示例代码如下:

/**

* 接收者对象

*/

public class Receiver {

/**

* 示意方法,真正执行命令相应的操作

*/

public void action(){

//真正执行命令操作的功能代码

}

}

(4)接下来看看Invoker对象,示例代码如下:

/**

* 调用者

*/

public class Invoker {

/**

* 持有命令对象

*/

private Command command = null;

/**

* 设置调用者持有的命令对象

* @param command 命令对象

*/

public void setCommand(Command command) {

this.command = command;

}

/**

* 示意方法,要求命令执行请求

*/

public void runCommand() {

//调用命令对象的执行方法

command.execute();

}

}

(5)再来看看Client的实现,注意这个不是我们通常意义上的测试客户端,主要功能是要创建命令对象并设定它的接收者,因此这 里并没有调用执行的代码,示例代码如下:

public class Client {

/**

* 示意,负责创建命令对象,并设定它的接收者

*/

public void assemble(){

//创建接收者

Receiver receiver = new Receiver();

//创建命令对象,设定它的接收者

Command command = new ConcreteCommand(receiver);

//创建Invoker,把命令对象设置进去

Invoker invoker = new Invoker();

invoker.setCommand(command);

}

}

2.4  使用命令模式来实现示例

要使用命令模式来实现示例,需要先把命令模式中所涉及的各个部分,在实际的示例中对应出来,然后才能按照命令模式的结构来设计和实现 程序。根据前面描述的解决思路,大致对应如下:

  • 机箱上的按钮就相当于是命令对象
  • 机箱相当于是Invoker
  • 主板相当于接收者对象
  • 命令对象持有一个接收者对象,就相当于是给机箱的按钮连上了一根连接线
  • 当机箱上的按钮被按下的时候,机箱就把这个命令通过连接线发送出去。

主板类才是真正实现开机功能的地方,是真正执行命令的地方,也就是“接收者”。命令的实现对象,其实是个“虚”的实现,就如同那根连接线,它哪知道如何实 现啊,还不就是把命令传递给连接线连到的主板。
使用命令模式来实现示例的结构如图3所示:


图3  使用命令模式来实现示例的结构示意图
还是来看看示例代码,会比较清楚。
(1)定义主板
根据前面的描述,我们会发现,真正执行客户命令或请求的是主板,也只有主板才知道如何去实现客户的命令,因此先来抽象主板,把它用对象描述出来。
先来定义主板的接口,最起码主板会有一个能开机的方法,示例代码如下:

/**

* 主板的接口

*/

public interface MainBoardApi {

/**

* 主板具有能开机的功能

*/

public void open();

}

定义了接口,那就接着定义实现类吧,定义两个主板的实现类,一个是技嘉主板,一个是微星主板,现在的实现是一样的,但是不同的主板对同一个命令的操作可以 是不同的,这点大家要注意。由于两个实现基本一样,就示例一个,示例代码如下:

/**

* 技嘉主板类,开机命令的真正实现者,在Command模式中充当Receiver

*/

public class GigaMainBoard implements MainBoardApi{

/**

* 真正的开机命令的实现

*/

public void open(){

System.out.println(“技嘉主板现在正在开机,请等候”);

System.out.println(“接通电源……”);

System.out.println(“设备检查……”);

System.out.println(“装载系统……”);

System.out.println(“机器正常运转起来……”);

System.out.println(“机器已经正常打开,请操作”);

}

}

微星主板的实现和这个完全一样,只是把技嘉改名成微星了。
(2)定义命令接口和命令的实现
对于客户来说,开机就是按下按钮,别的什么都不想做。把用户的这个动作抽象一下,就相当于客户发出了一个命令或者请求,其它的客户就不关心了。为描述客户 的命令,现定义出一个命令的接口,里面只有一个方法,那就是执行,示例代码如下:

/**

* 命令接口,声明执行的操作

*/

public interface Command {

/**

* 执行命令对应的操作

*/

public void execute();

}

有了命令的接口,再来定义一个具体的实现,其实就是模拟现实中机箱上按钮的功能,因为我们按下的是按钮,但是按钮本身是不知道如何启动电脑的,它需要把这 个命令转给主板,让主板去真正执行开机功能。示例代码如下:

/**

* 开机命令的实现,实现Command接口,

* 持有开机命令的真正实现,通过调用接收者的方法来实现命令

*/

public class OpenCommand implements Command{

/**

* 持有真正实现命令的接收者——主板对象

*/

private MainBoardApi mainBoard = null;

/**

* 构造方法,传入主板对象

* @param mainBoard 主板对象

*/

public OpenCommand(MainBoardApi mainBoard) {

this.mainBoard = mainBoard;

}

public void execute() {

//对于命令对象,根本不知道如何开机,会转调主板对象

//让主板去完成开机的功能

this.mainBoard.open();

}

}

由于客户不想直接和主板打交道,而且客户根本不知道具体的主板是什么,客户只是希望按下启动按钮,电脑就正常启动了,就这么简单。就 算换了主板,客户还是一样的按下启动按钮就可以了。
换句话说就是:客户想要和主板完全解耦,怎么办呢?
这就需要在客户和主板之间建立一个中间对象了,客户发出的命令传递给这个中间对象,然后由这个中间对象去找真正的执行者——主板,来完成工作。
很显然,这个中间对象就是上面的命令实现对象,请注意:这个实现其实是个虚的实现,真正的实现是主板完成的,在这个虚的实现里面,是通过转调主板的功能来 实现的,主板对象实例,是从外面传进来的。
(3)提供机箱
客户需要操作按钮,按钮是放置在机箱之上的,所以需要把机箱也定义出来,示例代码如下:

/**

* 机箱对象,本身有按钮,持有按钮对应的命令对象

*/

public class Box {

/**

* 开机命令对象

*/

private Command openCommand;

/**

* 设置开机命令对象

* @param command 开机命令对象

*/

public void setOpenCommand(Command command){

this.openCommand = command;

}

/**

* 提供给客户使用,接收并响应用户请求,相当于按钮被按下触发的方法

*/

public void openButtonPressed(){

//按下按钮,执行命令

openCommand.execute();

}

}

(4)客户使用按钮
抽象好了机箱和主板,命令对象也准备好了,客户想要使用按钮来完成开机的功能,在使用之前,客户的第一件事情就应该是把按钮和主板组装起来,形成一个完整 的机器。
在实际生活中,是由装机工程师来完成这部分工作,这里为了测试简单,直接写在客户端开头了。机器组装好过后,客户应该把与主板连接好的按钮对象放置到机箱 上,等待客户随时操作。把这个过程也用代码描述出来,示例代码如下:

public class Client {

public static void main(String[] args) {

//1:把命令和真正的实现组合起来,相当于在组装机器,

//把机箱上按钮的连接线插接到主板上。

MainBoardApi mainBoard = new GigaMainBoard();

OpenCommand openCommand = new OpenCommand(mainBoard);

//2:为机箱上的按钮设置对应的命令,让按钮知道该干什么

Box box = new Box();

box.setOpenCommand(openCommand);

//3:然后模拟按下机箱上的按钮

box.openButtonPressed();

}

}

运行一下,看看效果,输出如下:

技嘉主板现在正在开机,请等候

接通电源……

设备检查……

装载系统……

机器正常运转起来……

机器已经正常打开,请操作

你可以给命令对象组装不同的主板实现类,然后再次测试,看看效果。
事实上,你会发现,如果对象结构已经组装好了过后,对于真正的客户端,也就是真实的用户而言,任务就是面对机箱,按下机箱上的按钮,就可以执行开机的命令 了,实际生活中也是这样的。
(5)小结
如同前面的示例,把客户的开机请求封装成为一个OpenCommand对象,客户的开机操作就变成了执行OpenCommand对象的方法了?如果还有其 它的命令对象,比如让机器重启的ResetCommand对象;那么客户按下按钮的动作,就可以用这不同的命令对象去匹配,也就是对客户进行参数化。
用大白话描述就是:客户按下一个按钮,到底是开机还是重启,那要看参数化配置的是哪一个具体的按钮对象,如果参数化的是开机的命令对象,那就执行开机的功 能,如果参数化的是重启的命令对象,那就执行重启的功能。虽然按下的是同一个按钮,但是请求是不同的,对应执行的功能也就不同了。
在模式讲解的时候会给大家一个参数化配置的示例,这里就不多讲了。至于对请求排队或记录请求日志,以及支持可撤销的操作等功能,也放到模式讲解里面。

[转载]jquery :nth-child()选择器的简单应用

mikel阅读(1020)

[转载]jquery :nth-child()选择器的简单应用 – 我是一个不入流的Coder. – 博客园.

今天项目中遇到过一个这样的问题,就是希望读出来的文章列表能够每隔五个加一个分割条,而不是每个都加。

通过网上咨询使用这个选择器便很容易的解决。特此记录一下。

下面是主要的代码

js脚本:

<script type=”text/JavaScript”>
$(document).ready(
function () {
//每隔五行给li加一个样式
$(‘.article_li li:nth-child(5n)’).addClass(‘liborder’);
$(‘.article_li li:last’).addClass(‘liborder’);
}
);
</script>

html代码:

<ul class=”article_li”>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点物业 税:长沙暂不试点</a>
</li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
<li>
<label class=”datename”>
<span>2010-06-12 08:37:59 </span>
</label>
<a href=”/a/xinwenzixun/caishuidongtai/20100612/2323.html”>物业税:长沙暂不试点& lt;/a> </li>
</ul>

具体的用法这里就不写了,大家可以参考

http://www.cnblogs.com/Elgin/archive/2010/05/24/1742563.html

http://www.2ndvisual.com/xhtml/css/20616.html

效果图如下:

[转载]CSS未知高度垂直居中

mikel阅读(1140)

[转载]CSS未知高度垂直居中 – Ruby’s Louvre – 博客园.

最近群里这个问题比较热门,决定把我收藏的方法分享大家。在开始时,我们先看一下万能的table实现。

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta content="IE=8" http-equiv="X-UA-Compatible"/>
<title>司徒正美 CSS垂直居中</title>
<style type="text/css">
.container{
width:500px;/*装饰*/
height:500px;
background:#B9D6FF;
border: 1px solid #CCC;
}
</style>
</head>
<body>
<h1>垂直居中 (table)</h1>
<div class='container'>
<table width="100%" height="100%">
<tr>
<td align="center" valign="middle">
</td>
</tr>
</table>
</div>
</body>
</html>

好了,我们看其CSS实现。凡是table能做到的,CSS都能做的,但各浏览器在CSS的差异比较大,因此要兼容它们难度很大。这涉及许多细节, 各种流啊,display的表现效果与CSS hack,IE早些年搞了大堆的私有属性,这也有待我们深一步挖掘。我们先看最简单的实现,背景图片法——

背景图片法

CSS表达式法

绝对定位法

display:inline-block法

writing-mode法

记得淘宝也搞一个font-size法,但我觉得上下差异比较大,就不收录了。怿飞的博客亦提到过一韩国人有个巧妙的实现,但日久链接失效了,谁收 藏了也请提供一下。

[转载]一篇UI规范文件

mikel阅读(1051)

[转载]一篇UI规范文件 – 笑破天的博客 – 博客园.

这是一个UI模板规范,在做B/S版应用程序时比较适用,其实这样的东西算不上什么正规的规范,只是为了适应我 们现在面对的开发环境和组织流程做的一些权宜的努力,和解决了一些与程序沟通和接口的问题,尽量避免误会和摩擦。

一 适用环境和对象
二  必要性
三 技术原则
四 代码编写规范
五 页面模版使用规范

一 适用环境和对象
本规范适用基于浏览器的B/S版软件项目开 发工作。开发流程中的模版页面编写和模版文件套用工作必须遵照此规范执行。适用对象为开发编码人员、UI设计人员、模版编写人员、界面测试人员等。
基 于客户端的C/S版软件开发工作不适用本技术规范。

二 必要性
本规范旨在制订开发编码人员和UI模版编写人员之间在工作交叉部分的技术标准,使他们遵循同 一操作规范,利于交叉工作的平缓顺利交接。以标准化方式,提高沟通和技术协作的水平,提高工作效率。减少和改变责任不明,任务不清,和由此产生的信息沟通 不畅、反复修改、重复劳动、效率低下的现象。

三 技术原则
代码规范化书写
代码规范化书写实现了脚本整体风格的一致,保证了同一个人不同时期 写的脚本风格保持一致,以及同一个工作组中不同的开发人员编写的脚本风格保持一致。因为开发不可能在孤立中进行,所以代码规范化书写是项目组人员合作沟通 的前提。

数据层、结构层、表现 层分离
数据内容就是页面实际要传达的真正信息,包含数据、文档或者图片等。这里强调的“真正”,是指纯粹的数据信息本身。把信息内容以一种合适的 方式格式化,简言之就是页面排版,例如:分成标题、作者、章、节、段落和列表等,使内容更加具有逻辑性,条理清晰易读易懂,叫做“结构 (Structure)” 虽然定义了结构,但是内容还是相同的样式没有改变,例如标题字体没有变大,正文的颜色也没有变化,没有背景,没有修饰。所有这些用来改变内容外观的东西, 称之为“表现(Presentation)” “表现”的作用使内容看上去漂亮、赏心悦目、打动人心!

所有HTML和XHTML页面就是由“结构、表现和行为”这三方面 组成的。抽象一点理解,内容是基础层,然后是附加上去结构层和表现层,人对页面内容的交互及操作效果叫做“行为(Behavior)”,

对于数据、结构与表现 相分离,最早是在软件开发架构理论中提出来的。UI设计师设计出页面模版,程序员负责内容数据的嵌入,数据可能是从数据库中提取出来,也可能是静态写入的 提示性文字,最后形成一个新的页面展示给软件操作者。模版文件的结构利用HTML+XHTML标签来定义,而所有涉及表现的东西通通剥离出来,把它放到一 个单独的文件里,这个单独的文件就是CSS。

数据、结构与表现相分离的好处是:
程序员不需要过多的思考页面显示问题,而只需要根据模版效果把数 据放入模版相应的位置。界面的结构和表现由UI设计师负责。填入结构的数据自觉套用设计好了的表现效果。最后呈现一个实现功能的完整界面。
表现层 的分离保持整个软件界面视觉的一致性,使改版也变得非常简单,修改样式表就可以了;
由于结构清晰,数据层相对独立,对数据的集成、更新、处理和再 利用也更加方便灵活;

四 代码 编写规范

(一)目录结构及命名 规则

目录结构规范
1、 目录建立的原则:以最少的层次提供最清晰简便的访问结构。
2、根目录一般只存放index.htm以及其他必须的系统文件
3、在根目录中 原则上应该按照系统的栏目结构,给每一个栏目开设一个目录,根据需要在每一个栏目的目录中开设一个images 和media 的子目录用以放置此栏目专有的图片和多媒体文件,如果这个栏目的内容特别多,又分出很多下级栏目,可以相应的再开设其他目录。根目录下的images用于 存放各页面都要使用的公用图片,子目录下的images目录存放本栏目页面使用的私有图片
4、所有JS,ASP,PHP等脚本存放在根目录下的 scripts目录
5、所有CGI程序存放在根目录下的cgi-bin目录
6、所有CSS文件存放在根目录下style目录
7、 每个语言版本存放于独立的目录。例如:简体中文gb
8、所有flash, avi, ram, quicktime 等多媒体文件存放在根目录下的media目录
9、temp 子目录放客户提供的各种文字图片等等原始资料,以时间为名称开设目录,将客户陆续提供的资料归类整理。

文件和目录命名规范
1、文件命名的原则:以最少的字母达到最容 易理解的意义。
2、每一个目录中包含的缺省html 文件,文件名统一用index.htm
3、文件名称统一用小写的英文字母、数字和下 划线的组合,不得包含汉字、空格和特殊字符
4、尽量按单词的英语翻译为名称。例如:feedback(信息反馈),aboutus(关于我们) 不到万不得已不要以拼音作为目录名称
5、多个同类型文件使用英文字母加数字命名,字母和数字之间用_分隔。例如:news_01.htm。注意, 数字位数与文件个数成正比,不够的用0补齐。例如共有200条新闻,其中第18条命名为news_018.htm

图片的命名规范
1、 名称分为头尾两两部分,用下划线隔开。
2、头部分表示此图片的大类性质。例如: 放置在页面顶部的广告、装饰图案等长方形的图片我们取名:banner ;标志性的图片我们取名为:logo ;在页面上位置不固定并且带有链接的小图片我们取名为button ;在页面上某一个位置连续出现,性质相同的链接栏目的图片我们取名:menu ;装饰用的照片我们取名:pic ;不带链接表示标题的图片我们取名:title 依照此原则类推。
3、尾部分用来表示图片的具体含义,用英文字 母表示。例如:banner_sohu.gif banner_sina.gif menu_aboutus.gif menu_job.gif title_news.gif logo_police.gif logo_national.gif pic_people.jpg pic_hill.jpg.

4、有onmouse效果的图片,两张分别在原有文件名后加”_on”和”_off”命名

其它文件命名规范
1、 js的命名原则以功能的英语单词为名。例如:广告条的js文件名为:ad.js
2、所有的CGI文件后缀为cgi。所有CGI程序的配置文件为 config.cgi

(二)  html编写规则

一般原则
1、在编写模版文件,排布结构表格之前,要思考一个最佳方案,表格的嵌套尽量控制在三层以内;要考 虑程序套用的可实现性、通用性、灵活性、预见性,所有内容均采用积木式组织,可替换和删除,并对总体结构不会造成破坏性影响
2、尽量避免 <colspan> <rowspan> 两个标记,经验表明,这两个标记会带来许多麻烦
3、一个网页要尽量避免用整个 一张大表格,所有的内容都嵌套在这个大表格之内。因为浏览器在解释页面元素时,是以表格为单位逐一显示,如果一张网页是嵌套在一个大表格之内,那么很可能 造成的后果就是,当浏览者敲入网址,他要先面对一片空白很长时间,然后所有的网页内容同时出现。如果必须这样做,请使用 <tbody>标记,以便能够使这个大表格分块显示
4、排版中经常会遇到需要进行首行缩进的处理,不要使用全角空格来达到效果,规范 的做法是在样式表中定义 p { text-indent: 2em; } 然后给每一段加上 <p> 标记,注意,一般情况下,请不要省略 </p> 结束标记
5、原则上,我们禁止用 <img width=? height=?> 来人为干预图片显示的尺寸,而且建议 <img> 标签中不要带上width 和height 两个属性,这是因为制作过程中,图片往往需要反复的修改,这样可以避免人为干预图片显示的尺寸,尽可能的发挥浏览器自身的功能;但是这样的一个副作用是当 网页还未加载图片时,不会留出图片的站位大小,可能会造成网页在加载过程中抖动(如果图片是插在一个固定大小的表格里的,不会有这个现象),尤其是当图片 的尺寸较大时,这种现象会很明显,所以当预料到这种会明显导致网页抖动的情况会发生时,务必在最后给 <img>附上 width 和 height 属性
6、为了最大程度的发挥浏览器自动排版的功能,在一段完整的文字中尽量不要使用<br> 来人工干预分段
7、 不同语种的文字之间应该有一个半角空格,但避头的符号之前和避尾的符号之后除外,汉字之间的标点要用全角标点,英文字母和数字周围的括号应该使用半角括号
8、 为贯彻结构层和表现层分离的原则,严禁使用传统的HTML3.2/4.0控制表现的标签,例如<font>,<b>,还有本意用 于结构后来被滥用于控制表现的标签,例如:<h1>,<table>等。所有的字号都应该用样式表来实现,禁止在页面中出现 <font size= > 标记,<b> </b> <h1> </h1>标记,严禁在结构页面写表现标签
9、不要在网页 中连续出现多于一个的也尽量少使用全角空格(英文字符集下,全角空格会变成乱码),空白应该尽量使用 text-indent, padding, margin, hspace, vspace 以及透明的gif 图片来实现。
10、中英文混排时,我们尽可能的将英文和数字定义为 verdana 和arial 两种字体
11、行距建议用百分比来定义,常用的两个行距的值是line-height:120%/150%
12、 系统中的路径全部采用相对路径
13、为保证系统和浏览器的兼容性,当设置背景图片时,要坚持用双引号。
14、“网页大小”为网页的所有文 件大小的总和,包括HTML文件和所有的嵌入的对象。页面大小保持在34K以下为合适

代码规则
head区标识(head区是指首页HTML代码的<head> 和</head>之间的内容)
1、公司版权注释
<!–
Generator: 中软融鑫
Creation Data: 2005-8-1
Original Author: 张三
–>

2、网页显示字符集
简体中文:
<META. HTTP-EQUIV=”Content-Type” CONTENT=”text/html; charset=gb2312″>
繁体中 文:
<META. HTTP-EQUIV=”Content-Type” CONTENT=”text/html; charset=BIG5″>
英 语:
<META. HTTP-EQUIV=”Content-Type” CONTENT=”text/html; charset=iso-8859-1″>
?
3、简介
<META. NAME=”DESCRIPTION” CONTENT=”这里填您网站的简介”>?

4、网页的css文件定义,所有css文件尽量采用外部调用
<LINK href=”style/style.css” rel=”stylesheet” type=”text/css”>

5、网页标题
<title> 这里是你的网页标题</title>

6、所有的JavaScript脚本尽量采取外部调用
<SCRIPT. LANGUAGE=”JavaScript” SRC=”script/xxxxx.js”></SCRIPT>

head区可以选择加 入的标识
7、设定网页的到期时间。一旦网页过期,必须到fwq上重新调阅。
<META. HTTP-EQUIV=”expires” CONTENT=”Wed, 26 Feb 1997 08:21:57 GMT”>

8、禁止浏览器从本地 机的缓存中调阅页面内容。
<META. HTTP-EQUIV=”Pragma” CONTENT=”no-cache”>

9、用来防止别人在框 架里调用你的页面。
<META. HTTP-EQUIV=”Window-target” CONTENT=”_top”>

10、自动跳转。
<META. HTTP-EQUIV=”Refresh” CONTENT=”5;URL=http://www.yahoo.com”>
5指时间停留 5秒。

11、网页搜索机器人 向导.用来告诉搜索机器人哪些页面需要索引,哪些页面不需要索引。
<META. NAME=”robots” CONTENT=”none”>
CONTENT的参数有all,none,index,noindex,follow,nofollow。 默认是all。

12、收藏 夹图标
<link rel = “Shortcut Icon” href=”favicon.ico”>

13、搜索关键字
<META. NAME=”keywords” CONTENT=”关键字1,关键字2,关键字3,…”>

head区以下的标记
1、body标记
为了保证浏 览器的兼容性,必须设置页面背景
<body bgcolor=”#FFFFFF”>

2、table标记
在写 <table> 互相嵌套时,严格按照的规范,对于单独的一个<table>来说,<tr>,<td>各缩进两个半角空格,结束标记 和开始标记平齐。<td> 中如果还有嵌套的表格,<table>也缩进两个半角空格,如果<td>中没有任何嵌套的表格,</td> 结束标记应该与 <td> 处于同一行,不要换行。
正确写法:
a\
<table width=”100%”? border=”0″ cellspacing=”0″ cellpadding=”0″>
<tr>
<td>&nbsp;</td>
</tr>
<tr>
<td>
<table width=”100%”? border=”0″ cellspacing=”0″ cellpadding=”0″>
<tr>
<td>&nbsp;</td>
</tr>
</table>
</td>
</tr>
</table>

b\
<td><img src=”../images/sample.gif”></td>

错误写法
a\
<table width=”100%”? border=”0″ cellspacing=”0″ cellpadding=”0″>
<tr>
<td>&nbsp;</td>
</tr>
<tr>
<td><table width=”100%”? border=”0″ cellspacing=”0″ cellpadding=”0″>
<tr>
<td>&nbsp;</td>
</tr>
</table>
</td>
</tr>
</table>

b\
<td><img src=”../images/sample.gif”>
</td>
这是因为浏览器认为换行相当于一个半角空格,以 上不规范的写法相当于无意中增加一个半角空格,如果确实有必要增加一个半角空格,也应该这样写:
<td><img src=”../images/sample.gif”> </td>

于同一个级别的 <table> 一定是左首对齐的,另外不允许没有任何内容的空的单元格存在,高度大于等于12px 的单元格应该 在 <td> 和 </td> 之间写一个&nbsp;,如果高度小于12px, 则应该 在 <td> 和 </td> 之间插入一个1*1 大小的透明的gif 图片,这是因为某些浏览器认为空单元格非法而不会予以解释。如果代码顺序较乱,在DW中可以通过command->apply souce formatting进行重新整理!

3、Width 和height标记
一般情况下只有一列的表格,width 写在<table> 的标签内,只有一行的表格,height 写在 <table> 的标签内,多行多列的表格,width 和height 写在第一行或者第一列的 <td> 标签内。总之遵循一条原则:不出现多于一个的控制同一个单元格大小的height 和width, 保证任何一个width 和height 都是有效的,也就是改动代码中任何一个width 和height 的数值,都应该在浏览器中看到变化。
a、只一列的表格的width标记
<table width=”100%”? border=”0″ cellspacing=”0″ cellpadding=”0″>
<tr>
<td>&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
</tr>
</table>
b、 只一行的表格的height标记
<table width=”100%” height=”30″? border=”0″ cellpadding=”0″ cellspacing=”0″>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>
c、 多行多列表格的width和height标记
<table border=”0″ cellpadding=”0″ cellspacing=”0″>
<tr>
<td width=”100″ height=”30″>&nbsp;</td>
<td width=”200″>&nbsp;</td>
<td width=”300″>&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>

4、table的 width属性

为遵循页面 结构灵活性、通用性原则,table的width属性原则上全部写成100%或者不写width属性,不推荐写成其他非100%宽度属性。留空显示效果通 过其给外部td施加style的padding属性实现。

<table width=”100%”? border=”1″ cellspacing=”0″ cellpadding=”0″>
<tr>
<td width=”200″ bgcolor=”#FF0000″ style=”padding:20px; “>
<table width=”100%” border=”1″ cellpadding=”0″ cellspacing=”0″ bgcolor=”#FFFFFF”>
<tr>
<td>table宽度 100%</td>
</tr>
<tr>
<td>&nbsp;</td>
</tr>
</table>
</td>
<td>&nbsp;</td>
</tr>
</table>

需要说明的是这里td的style虽然是css的写法,但不属于表现层的内容,而是属于结构层 的内容,所以可以直接写在html标记中间。

5、数据列表表格代码写法
表格外加上一个<div>,并对<div>赋一个 id,即<div id =list>,然后通过样式表对这个id下的所有html元素进行控制,
用<th>表示表头
设 置每列宽度的位置在表头对应的<th>中,其中列表项中,字数最多或者字数不定的一项不设置宽度。
宽度的值依据列表项内容的多少来 定,2个字的30px,三个字40px,时间、年月日(比如2004-11-11)80-120px,
类似于标题的列表项,表格对齐方式为左对齐 (align=left),时间,人名一般居中对齐,数据一般右对齐(align=right)。
对齐页面内容时不要用div来对齐,直接在td 或th中写align=…
表头文字一般不折行,方法是在<th>中加上nowrap,或者通过样式表来控制

<table width=”100%” border=”0″ cellspacing=”0″ cellpadding=”0″>
<tr>
<th width=”30″ nowrap>选择</th>
<th align=”left” nowrap>标题</th>
<th width=”80″ nowrap>发表人</th>
<th width=”120″ nowrap>时间</th>
<th width=”40″ nowrap>大小</th>
</tr>
<tr>
<td>&nbsp;</td>
<td align=”left”>&nbsp;</td>
<td align=”center”>&nbsp;</td>
<td align=”center”>&nbsp;</td>
<td align=”right”>&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td align=”left”>&nbsp;</td>
<td align=”center”>&nbsp;</td>
<td align=”center”>&nbsp;</td>
<td align=”right”>&nbsp;</td>
</tr>
</table>

(三)  css编写规则

css文件 调用写法
1、所有的CSS的尽量采用外部调用,特殊情况才允许使用内置html写法。
<LINK href=”style/style.css” rel=”stylesheet” type=”text/css”>

css文件结构组织
1、 文件提头,css文件名称、时间、作者

2、 将不同目的和效果的CSS选择符分别编组,编组分层级使结构清晰,便于查对。并恰当地成块注释,注释要说 明施加的页面文件的对象。顶级注释用*TOP*打头,次级注释不用。

.headtext {
font-size: 14px;
color: #ffffff;
font-weight: bold;
}?
.headtext a:link {
color: #ffffff;
text-decoration: none;
}
.headtext a:visited {
color: #ffffff;
text-decoration: none;
}
.headtext a:hover {
color: FED078;
text-decoration:none ;
}

#clientcard {
align:left;
}
#clientcard th {
height:20;
font-size: 12px;
color: #737373;
padding-left:10;
font-weight: bold;
background-attachment: fixed;
background:url(images/dot2.gif)

background-repeat: no-repeat;
background-position: left center;
}
#clientcard td {
height:20;
font-size: 12px;
color: #FD783A;
padding-right:25;
}

3、选择符分组的顺序是重定义的最先,伪类其次,自定义最后。便于自己和他人阅读。
例 如:

BODY {
margin-left: 0px;

}

TD {
font-size: 12px;

}

a:link {
color:?#484848;
text-decoration: none;
}
a:visited {
color: #484848;
text-decoration: none;
}
a:hover {
color:#BD0800;
text-decoration: underline;
}

.ltreename {
font-size: 14px;

}

类和ID命名规则
1、 以功能和定义对象的位置,而不是外观为类和ID命名。例如创建了一个 .smallblue 类,后来打算将文字改大,颜色变为红色,这个类名就不再有任何意义了。所以,用更有描述性的名字如 .copyright 和.info-list更加合适。

单位
1、0不用单位
2、非零值要指明单位,指定字体、边距或大小时,必须指明所用的单位
例 如: padding: 0 2px 0 1em;
3、特例:line-height不需要单位

字号大小
1、为了保证不同浏览器上字号保持一致,字号像素px 来定义,一般使用中文宋体12px 和14.7px 这是经过优化的字号,黑体字或者宋体字加粗时,一般选用14.7px 的字号比较合适
例如: font-size: 12px;

顺序
1、a:link a:visited a:hover a:actived 要按照规范顺序写
2、 边框(border)、边距(margin)和补白(padding)的简写次序为:顺时针方向从上开始,即 Top, Right, Bottom, Left。
例如: margin: 0 1px 3px 5px;表示上边距为零,右边距为1px,依此类推。

组合选择符
1、 保持CSS短小对减少下载时间非常重要。尽量为选择符分组、利用继承(inheritance)以及使用简写(shorthand)来减少冗余。

使用图片
1、 css中经常遇到使用图片的情况, 图片的路径一律采用相对路径。
例如:

.hurdlename {
font-size: 14px;
color: #0B43C2;
height:25px;
font-weight: bold;
background-image: url(images/rbar_bg.gif);
background-repeat: repeat-y;
text-indent: 12px;
}

.but1{
background-image: url(../images/but1.gif);
font-size: 12px;
color: #000000;
border: 0;
width:85px;
height:26px;
cursor: hand;
}

2、使用图片替换技术时要考虑与系统和文件结构的亲和力。如果引用css的所有文件不在同一级相对路径,就会出 现css指定的图片无法显示的问题。在这种情况下不支持使用图片技术。建议采用filter技术
例如:

input.buttton {
filter:progid:DXImageTransform.Microsoft.Gradient(gradienttype=0, startcolorstr=#CFD1CF, endcolorstr=#EFEFEF);
border: #B5B6B5 1px solid;
font-size: 12px;
color: #000000;
cursor: hand;
height:24px;
background:#ffffff;
}

五 页面模版使用规范

页面模版使用规范的目 的是统一和约定UI设计、界面工程师与不同的程序编码人员的行为方式,光有了书写代码的规范还不能完全解决界面套用的统一性问题。因为不同的编码人员对同 一个模版的理解有可能不同,再加上个人工作习惯的不同,界面套用的结果往往很容易出现差异。哪怕是每人一点点差异,都可能使软件的质量收到很大的影响。

责任分工明确
1、 UI设计、界面工程师负责界面风格的设计和软件模版的编写,并监督界面套用的效果。对软件最终的界面负责。
2、 编码工程师负责软件业务逻辑的实现,软件模版的套用。对软件的数据和程序负责。
3、现实的情况是个别编码工程师在模版套用出现偏差后,在界面工程 师提出修改意见的时候拒绝修改,以开发进度、时间不够为由搪塞,甚至主观认为“这个(界面)不重要”致使界面工程师的作用得不到应有的发挥,影响软件产品 质量。
4、 解决办法是各负其责。界面问题提高重视程度,并纳入开发流程和进度管理之中。

界面模版交界过程
1、 模版文件制作完成后,在提交给编码工程师时,要简要说明模版的文件的使用说明和提醒。
2、 编码工程师和界面工程师密切合作,完全理解模版使用说明。
3、对界面结构层html的table嵌套关系理解清楚并明确和程序结合的用意。有和程 序不相配合的情况,进一步和界面工程师讨论,获得解决方案。不得在界面工程师不知情的情况下随意修改table结构、定位属性和嵌套关系。这样做的坏处是 虽然一个人解决了暂时的显示问题,但和其他编码工程师套用的结果出现不同。也不利于界面工程师控制总体界面。
4、 对表现层的界面元素和css文件选择符的对应关系。做到心中有数,理解一个模版文件,到套用其他文件时就能够举一反三。

5、编码工程师完全 理解了界面模版后,就能够顺畅的把数据层的内容放到结构层合适的位置,并指定表现层合适的选择符属性。完成界面套用工作。

模版说明的内容
1、 总体的界面结构
2、 页面板块的布局和定位table的写法
3、 table嵌套的方式的理由
4、 不同功能的界面显示单元说明和使用方法
5、 css文件中选择符的使用说明,一般的都能理解,个别特殊的要着重说明。

Css文件的版本控制
Css 文件应引入版本控制的机制,项目组中应指定专人负责css文件的上传和修改。fwq的css文件和界面工程师的css文件应该同步更新。不支持编码工程师 随意添加选择符修改css文件。谁都可以改就没有标准,没有版本控制就做很难做到界面统一

[转载]NVelocity的宏使用

mikel阅读(991)

[转载]NVelocity的宏使用 – ∠角络 – 博客园.

一、NVelocity使用参数
示例:
1.建立宏
#macro( test $range $arrayList )

#end
2.调用宏
#test([-9,-1] [“favorite”, “color”])
通过以上示例,你只需要一个为每一个需要传递的参数提供了名称的#macro指令,这些参数用空 格进行分隔。如上例中#macro( test $range $arrayList )“test”是宏名,$range $arrayList是参数。用”#”+宏名(参数1,参数2…)来调用宏。

二、NVelocity递归调用

嵌套,最简单的情况就是在NVelocity 中用到macro里调用另外一个macro,这是在实际代码开发中使用得最频繁的一种。递归,是一种特殊类型的嵌套,它是在NVelocity中的 macro里调用自身,但这种情况并不太常见。

#macro( recurs $depth )
进入第 $depth 层<br/>

#set( $depth = $depth – 1 )

#if ( $depth > 0 )

#recurs( $depth )

#end

#set( $depth = $depth + 1 )

进入第 $depth 层<br/>

#end
#recurs( 3 )

执行结果:
进入第 3 层
进入第 2 层
进 入第 1 层
进入第 1 层
进入第 2 层
进入第 3 层
注:在递归调用时,注意 通常不要把一个对象的属性传为参数递归调用,上例中,如果$depth是一个对象的话,那么用#recurs( $depth.attribute)话,模板输出时候往往有问题,而且又查不出来,这里记录一下,忘以后不要出现这样的错误。究其原因,我想是由于是 object类型,往往在调用时认不出对象的类型吧(暂时只能这样去理解了,没深层次去研究过)。