随笔 - 16  文章 - 1 评论 - 6 trackbacks - 1
<2008年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

与我联系

搜索

 

常用链接

留言簿

我的标签

随笔分类

随笔档案

收藏夹

最新评论

阅读排行榜

评论排行榜

using System.Text.RegularExpressions;

        /// <summary>
        /// 按指定长度截取字符串(以字节计算长度)
        /// </summary>
        /// <param name="stringToSub"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static string GetFirstString(string stringToSub, int length)
        {
            if (System.Text.Encoding.Default.GetByteCount(stringToSub) <= length)
                return stringToSub;

            Regex regex = new Regex("[\u4e00-\u9fa5]+", RegexOptions.Compiled);
            char[] stringChar = stringToSub.ToCharArray();
            StringBuilder sb = new StringBuilder();
            int nLength = 0;
            bool isCut = false;
            for (int i = 0; i < stringChar.Length; i++)
            {
                if (regex.IsMatch((stringChar[i]).ToString()))
                {
                    sb.Append(stringChar[i]);
                    nLength += 2;
                }
                else
                {
                    sb.Append(stringChar[i]);
                    nLength = nLength + 1;
                }

                if (nLength > length)
                {
                    isCut = true;
                    break;
                }
            }
            if (isCut)
                return sb.ToString() + ""; //可加上省略号
            else
                return sb.ToString();
        }

posted @ 2008-08-21 11:15 zengjun 阅读(23) | 评论 (0)编辑
CSS IE6,IE7,FF兼容性
 

    原来CSS不止是IE和FF存在兼容性的问题,IE6和IE7也有问题。网上搜了两篇文章,借鉴一下。

一、绿色版IE7 让IE6和ie7共存

Windows IE7 安装后,IE6 就消失了,很不方便。好在老外搞出了可以独立运行的 IE7 绿色版。通过这个软件就可以让IE7 和ie6 共存你的电脑中了

1、访问 http://tools.veloc-it.com/tabid/58/grm2id/4/Default.aspx 下载 ie7 Standalone 这个工具。你也可以在这里下载:IE7 Standalone

2:解压缩 IE7-Release-v1.8.zip 到一个空目录中,例如 D:\Program Files\ie7_Final。

3:访问 http://www.microsoft.com/china/ 下载 Internet EXPlorer 7。将 IE7 的安装文件(ie7-WindowsXP-x86-chs.exe,我下载的是中文版,如果你下载的英文版,则需要像第4步那样做些修改)保存到 D:\Program Files\IE7_Final 目录中(关键就是要和 ie7-Release-v1.8.zip 解压缩出来的文件保存在同一个目录中)。www.pcp 供稿XP.comWindows/ie/downloads/default.mspx

4:用记事本编辑 IE7 Standalone Setup.bat,在第7行修改ie7-windowsXP-x86-enu.exe成ie7-WindowsXP-x86-chs.exe,保存并退出。如图:

PS:这里要说明一下,因为我下载的是中文版,而这个NB的工具是老外写的,所以就我要做些改动,如果你下载的是英文版,第4步省略。

5:运行 D:\Program Files\IE7_Final 目录中的 IE7 Standalone Setup.bat 批处理程序。这个程序会解压缩 ie7 的安装文件到 Installation 子目录中。(中途可能会提示你安装Hotfix (KB915865),放心,那是安全的)

6:运行 D:\Program Files\IE7_Final 目录中的 ie7.bat 就可以启动 ie7 了。注意启动的时候会出现一个 dos 窗口,不能关闭这个窗口,15 秒后这个窗口会自动关闭。

二、CSS hack:针对IE6,IE7,firefox显示不同效果

做网站时经常会用到,衡量一个DIV+CSS架构师的水平时,这个也很重要。

区别不同浏览器的CSS hack写法:

区别IE6与FF:
        background:orange;*background:blue;

区别IE6与IE7:
        background:green !important;background:blue;

区别IE7与FF:
        background:orange; *background:green;

区别FF,IE7,IE6:
        background:orange;*background:green !important;*background:blue;

注:IE都能识别*;标准浏览器(如FF)不能识别*;

IE6能识别*,但不能识别 !important,
IE7能识别*,也能识别!important;
FF不能识别*,但能识别!important;

IE6 IE7 FF
* ×
!important ×



------------------------------------------------------
另外再补充一个,下划线"_",
IE6支持下划线,IE7和firefox均不支持下划线。

IE6 IE7 FF
* ×
!important ×
_ × ×


于是大家还可以这样来区分IE6,IE7,firefox
: background:orange;*background:green;_background:blue;

注:不管是什么方法,书写的顺序都是firefox的写在前面,IE7的写在中间,IE6的写在最后面。

 


CSS HACK


以下两种方法几乎能解决现今所有HACK.

1, !important

随着IE7对!important的支持, !important 方法现在只针对IE6的HACK.(注意写法.记得该声明位置需要提前.)
<stylegt;
#wrapper
{
width: 100px!important; /* IE7+FF */
width: 80px; /* IE6 */
}
</stylegt;


2, IE6/IE77对FireFox

*+html 与 *html 是IE特有的标签, firefox 暂不支持.而*+html 又为 IE7特有标签.
<style>
#wrapper
{
#wrapper { width: 120px; } /* FireFox */
*html #wrapper { width: 80px;} /* ie6 fixed */
*+html #wrapper { width: 60px;} /* ie7 fixed, 注意顺序 */
}
</style>


注意:
*+html 对IE7的HACK 必须保证HTML顶部有如下声明:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

二、万能 float 闭合(非常重要!)

关于 clear float 的原理可参见 [How To Clear Floats Without Structural Markup]
将以下代码加入Global CSS 中,给需要闭合的div加上 ><style>
/* Clear Fix */

.clearfix:after
{
content:".";
display:block;
height:0;
clear:both;
visibility:hidden;
}
.clearfix
{
display:inline-block;
}
/* Hide from IE Mac */
.clearfix {display:block;}
/* End hide from IE Mac */
/* end of clearfix */
</style>

关于闭合浮动元素(clearing float)的方法现在已经很多了,个人认为简单实用的方法就是使用:after伪类动态的嵌入一个用于清除浮动的元素,可惜代码量太大了,看上去不够简洁。

现在看到有个方法超级简单。介绍一下这个方法。原文在:http://annevankesteren.nl/2005/03/clearing-floats

这 一方面的原理是,外围元素之所以不能很好的延伸,问题出在了overflow上,因为overflow不可见(见W3C的解释)。现在只要将给外围元素添 加一个“overflow:auto”,就可以解决问题,结果是除了IE,真的可以解决。下来就要解决ID的问题了,再加上“_height:1%”,这 个问题就完全解决了。

下面的例子作为比较
1、没有闭合浮动元素;2、非IE下闭合浮动元素;3、完全闭合元素。相关代码如下:

XHTML代码:

Example Source Code [ww
w.52css.com]
<div id="wrap">
<div class="column_left">
   <h1>Float left</h1>
</div>
<div class="column_right">
   <h1>Float right</h1>
</div>
</div>


CSS样式:

Example Source Code [ww
w.52css.com]
#wrap{ border:6px #ccc solid; overflow:auto; _height:1%;}
   .column_left{ float:left; width:20%; padding:10px;}
   .column_right{ float:right; width:75%; padding:10px; border-left:6px #eee solid;}

 


三、其他兼容技巧(再次啰嗦)

1, FF下给 div 设置 padding 后会导致 width 和 height 增加, 但IE不会.(可用!important解决)
2, 居中问题.
1).垂直居中.将 line-height 设置为 当前 div 相同的高度, 再通过 vertical-align: middle.( 注意内容不要换行.)
2).水平居中. margin: 0 auto;(当然不是万能)
3, 若需给 a 标签内内容加上 样式, 需要设置 display: block;(常见于导航标签)
4, FF 和 IE 对 BOX 理解的差异导致相差 2px 的还有设为 float的div在ie下 margin加倍等问题.
5, ul 标签在 FF 下面默认有 list-style 和 padding . 最好事先声明, 以避免不必要的麻烦. (常见于导航标签和内容列表)
6, 作为外部 wrapper 的 div 不要定死高度, 最好还加上 overflow: hidden.以达到高度自适应.
7, 关于手形光标. cursor: pointer. 而hand 只适用于 IE.

1 针对firefox ie6 ie7的css样式
现在大部分都是用!important来hack,对于ie6和firefox测试可以正常显示,
但是ie7对!important可以正确解释,会导致页面没按要求显示!找到一个针
对IE7不错的hack方式就是使用“*+html”,现在用IE7浏览一下,应该没有问题了。
现在写一个CSS可以这样:

#1 { color: #333; } /* Moz */
* html #1 { color: #666; } /* IE6 */
*+html #1 { color: #999; } /* IE7 */
那么在firefox下字体颜色显示为#333,IE6下字体颜色显示为#666,IE7下字体颜色显示为#999。

2 css布局中的居中问题
主要的样式定义如下:

body {TEXT-ALIGN: center;}
#center { MARGIN-RIGHT: auto; MARGIN-LEFT: auto; }
说明:
首先在父级元素定义TEXT-ALIGN: center;这个的意思就是在父级元素内的内容居中;对于IE这样设定就已经可以了。
但在mozilla中不能居中。解决办法就是在子元素定义时候设定时再加上“MARGIN-RIGHT: auto;MARGIN-LEFT: auto; ”
需要说明的是,如果你想用这个方法使整个页面要居中,建议不要套在一个DIV里,你可以依次拆出多个div,
只要在每个拆出的div里定义MARGIN-RIGHT: auto;MARGIN-LEFT: auto; 就可以了。

3 盒模型不同解释.

#box{ width:600px; //for ie6.0- w\idth:500px; //for ff+ie6.0}
#box{ width:600px!important //for ff width:600px; //for ff+ie6.0 width /**/:500px; //for ie6.0-}

4 浮动ie产生的双倍距离

#box{ float:left; width:100px; margin:0 0 0 100px; //这种情况之下IE会产生200px的距离 display:inline; //使浮动忽略}
这里细说一下block,inline两个元素,Block元素的特点是:总是在新行上开始,高度,宽度,行高,边距都可以控制(块元素);Inline元素的特点是:和其他元素在同一行上,...不可控制(内嵌元素);

#box{ display:block; //可以为内嵌元素模拟为块元素 display:inline; //实现同一行排列的的效果 diplay:table;

5 IE与宽度和高度的问题

IE不认得min-这个定义,但实际上它把正常的width和height当作有min的情况来使。这样问题就大了,如果只用宽度和高度,
正常的浏览器里这两个值就不会变,如果只用min-width和min-height的话,IE下面根本等于没有设置宽度和高度。
比如要设置背景图片,这个宽度是比较重要的。要解决这个问题,可以这样:
#box{ width: 80px; height: 35px;}html>body #box{ width: auto; height: auto; min-width: 80px; min-height: 35px;}

6 页面的最小宽度

min-width是个非常方便的CSS命令,它可以指定元素最小也不能小于某个宽度,这样就能保证排版一直正确。但IE不认得这个,
而它实际上把width当做最小宽度来使。为了让这一命令在IE上也能用,可以把一个<div> 放到 <body> 标签下,然后为div指定一个类:
然后CSS这样设计:
#container{ min-width: 600px; width:expression(document.body.clientWidth < 600? "600px": "auto" );}
第一个min-width是正常的;但第2行的width使用了Javascript,这只有IE才认得,这也会让你的HTML文档不太正规。它实际上通过Javascript的判断来实现最小宽度。

7 清除浮动

.hackbox{ display:table; //将对象作为块元素级的表格显示}或者.hackbox{ clear:both;}
或者加入:after(伪对象),设置在对象后发生的内容,通常和content配合使用,IE不支持此伪对象,非Ie 浏览器支持,
所以并不影响到IE/WIN浏览器。这种的最麻烦的......#box:after{ content: "."; display: block; height: 0; clear: both; visibility: hidden;}

8 DIV浮动IE文本产生3象素的bug

左边对象浮动,右边采用外补丁的左边距来定位,右边对象内的文本会离左边有3px的间距.

#box{ float:left; width:800px;}#left{ float:left; width:50%;}#right{ width:50%;}*html #left{ margin-right:-3px; //这句是关键}
HTML代码<div id="box"> <div id="left"></div> <div id="right"></div></div>

9 属性选择器(这个不能算是兼容,是隐藏css的一个bug)

p[id]{}div[id]{}
这个对于IE6.0和IE6.0以下的版本都隐藏,FF和OPera作用
属性选择器和子选择器还是有区别的,子选择器的范围从形式来说缩小了,属性选择器的范围比较大,如p[id]中,所有p标签中有id的都是同样式的.

10 IE捉迷藏的问题

当div应用复杂的时候每个栏中又有一些链接,DIV等这个时候容易发生捉迷藏的问题。
有些内容显示不出来,当鼠标选择这个区域是发现内容确实在页面。
解决办法:对#layout使用line-height属性 或者给#layout使用固定高和宽。页面结构尽量简单。

11 高度不适应

高度不适应是当内层对象的高度发生变化时外层高度不能自动进行调节,特别是当内层对象使用
margin 或paddign 时。
例:
<div id="box">
p对象中的内容
</div>
CSS:#box {background-color:#eee; }
#box p {margin-top: 20px;margin-bottom: 20px; text-align:center; }
解决方法:在P对象上下各加2个空的div对象CSS代码:.1{height:0px;overflow:hidden;}或者为DIV加上border属性。

 

 

让你的IE7和IE6友好共存

 

IE7出来好长一段时间了,对于做WEB开发的人来说,这是新来的一个麻烦,因为考虑到浏览器的兼容性,我们在编写一个HTML页面时不得不顾虑多个浏览器的呈现效果,不同的IE版本支持的样式也是不一样的,因此,原来在IE6下的完美呈现不见得还能在IE7下一样完美。

  原来安装过IE7,结果把IE6给弄没了,这次不得不另寻他法,实际上就是借用一个第三方的小工具,让IE7在没有安装的情况下独立运行。

  下面介绍安装方法(注意:按照这种方法安装的IE7.0仅做调试开发用,其原来很多功能都不能体现出来):

  1、下载第三方工具IE7 Standalone

  官方下载地址:http://tools.veloc-it.com/tabid/58/grm2id/4/Default.aspx ,你也可以在这里下载:IE7 Standalone

  2、下载IE7.0安装包

  官方下载地址:http://www.microsoft.com/windows/ie/downloads/default.mspx ,如果你下载的是中文版,将其文件名更改为IE7-WindowsXP-x86-enu.exe。

  3、解压并安装

  解压第1步得到的压缩包,并将第2步下载的IE安装文件也放到该文件夹中,大致的文件夹布局如下:

  双击 IE7 Standalone Setup.bat 进行安装。安装完成后运行 IE7.bat ,蓝屏了,IE7也出来了。

posted @ 2008-07-31 09:38 zengjun 阅读(34) | 评论 (0)编辑

 

Asp.net中服务端控件事件是如何触发的

Asp.net 中在客户端触发服务器端事件分为两种情况:
一.   WebControls中的Button HtmlControls中的TypesubmitHtmlInputButton
这两种按钮最终到客户端的表现形式为:<input type="submit" value="Submit">,这是Form表单的提交按钮,点击以后会作为参数发送到服务端,参数是这样的:
控件的name属性=控件的value值,对应上面的例子就是:Submit1= Submit。服务器端会根据接收到的控件的name属性的这个key来得知是这个按钮被点击了,从而在服务端触发这个按钮的点击事件。
二.   HtmlControls 中的 TypebuttonHtmlInputButton 和其它所有的控件事件,比如LinkButton点击,TextBoxChange事件等等:
这些事件在客户端产生后会经过一个统一的机制发送到服务端。
 
1.首先asp.net页框架会使用两个Hidden域来存放表示是哪个控件触发的事件,以及事件的参数:
<!―表示触发事件的控件,一般是这个控件的name -->
<input type="hidden" value="" />
<!―表示触发事件的参数,一般是当某个控件有两个以上的事件时,用来区别是哪个事件 -->
<input type="hidden" value="" />
 
2.服务端会生成一个jscript的方法来处理所有这些事件的发送,这段代码是:
<script language="javascript" type="text/javascript">
    function __doPostBack(eventTarget, eventArgument)
    {
        var theform = document.WebForm2;
        theform.__EVENTTARGET.value = eventTarget;
        theform.__EVENTARGUMENT.value = eventArgument;
        theform.submit();
    }
</script>  

3.每个会引发服务端事件的控件都会在响应的客户端事件中调用上面的代码:
比如,HtmlControls 中的 TypebuttonHtmlInputButton的点击事件
<!―客户端的点击事件调用__doPostBackeventTarget 参数为'Button2',表示是name'Button2’控件触发的事件,eventArgument 为空,表示这个TypebuttonHtmlInputButton只有一个客户端触发的服务端事件-->
<input language="javascript" Button2','')" type="button" value="Button" />
又比如,TextBox控件的Change事件
<!―客户端的onchange事件调用__doPostBackeventTarget 参数为’TextBox1’,表示是name’TextBox1’控件触发的事件,而TextBox控件只有一个客户端触发的服务端事件TextChanged,故服务器就会去触发这个TextBoxTextChanged事件->
<input type="text" TextBox1','')" language="javascript" />
 
4.客户端触发事件后调用__doPostBack方法,将表示触发的控件源的eventTarget 和事件参数eventArgument分别付给两个隐藏域__EVENTTARGET__EVENTARGUMENT,然后提交Form,在服务端根据__EVENTTARGET__EVENTARGUMENT来判断是哪个控件的什么事件触发了。
 
第二章 PostBack的原理
__doPostBack是一个纯粹并且是非常简单的javascript函数,大部分的页面PostBack都是由它触发的。注意,这里是大部分,因为只有两个Web Server Control    会自己触发页面的PostBack,其它的所有控件都是通过__doPostBack函数触发页面的PostBack,那先来看一下这个函数的定义吧:
CODE1:
<input type="hidden" value="" />
<input type="hidden" value="" />
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
通过上面的代码可以看到,__doPostBack带有两个参数,eventTarget是标识将要引发页面PostBack的控件IDeventArgument参数提供了在引发页面PostBack事件时所带的额外参数。当然这个函数被函数时,这两个参数的值将赋值给页面的两个隐含变量__EVENTTARGET__EVENTARGUMENT,然后调用页面的submit方法提交页面表单。这就是为什么我们可以通过Request.Form[“__EVENTTARGET”]获取得到引发页面PostBack的控件ID的原因。
了解了__doPostBack函数后,我们可以很容易的利用它非常方便地自己触发自定义的PostBack事件。那上面也说了,大部分的控件都是调用
 
第三章 Button PostBack做法
引了页面的PostBack,只有两个控件是例外,Button ImageButton,正是因为它们不是通过调用__doPostBack来回发事件,所以通过表单隐含变量__EVENTTARGET__EVENTARGUMENT是无法获取得到引发PostBackButtonImageButtonID和参数值的,可通过下面的方式实现
1)在页面中加如 LinkButton ,页面就会在页面中加载POSTBACK所需的JS
<input type="hidden" value="" />
<input type="hidden" value="" />
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
 
2)利用GetPostBackEventReference给客户端生成__doPostBack()
如:
比如前台页面
<asp:Button id="Button1" runat="server" Text="Button"></asp:Button>
1
<href="#" onclick="document.getElementById('Button1').click()">触发服务器端按钮事件</a>
2
利用GetPostBackEventReference给客户端生成__doPostBack()
前台
<href="#" onclick="<%=PostBack()%>">触发服务器端按钮事件</a>
后台
protected string PostBack()
        {
            
return this.Page.GetPostBackEventReference(this.Button1,"haha");
        }
通过__EVENTARGUMENT="haha"可以判断是不是点了那个链接的PostBackButton1的按钮事件这么写:
if(Request["__EVENTARGUMENT" ]=="haha")
            {
                Response.Write("
这个是链接的PostBack");
            }
            
else
            {
                Response.Write("
这个不是链接的PostBack");
            }


 
Bug
问题:『使用__doPostBack会导致』
回发或回调参数无效。在配置中使用 <pages enableEventValidation="true"/> 或在页面中使用 <%@ Page EnableEventValidation="true" %> 启用了事件验证。出于安全目的,此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用 ClientScriptManager.RegisterForEventValidation 方法来注册回发或回调数据以进行验证。
问题分析及解决方案:『来源网络』
这个要具体分析。本来这个措施是asp.net2.0用来防止客户端欺诈服务器端的。例如本来输出到客户端的一个事件被触发时需要回发的命令是“__doPostback('ctl01$abc','user_1')”的,如果采取采取手段把回发参数由 user_1 改为 user_5 了,服务器端会重新核对输出的是不是user_5,发现和这个页面上一个输出的脚本不一致,就会产生这个异常。
但是,很多程序员写的程序按照过去的习惯(或者按照更加高级灵活的设计例如一些Ajax组件)没有考虑这个问题或者是忽略这个欺诈的可能性,写的程序可能会修改参数或者修改目标控件。
因此这样具体问题具体分析。不太可能跟浏览器距离服务器的远近有关,应该还是编程逻辑问题。你应该对出异常的画面以及所使用的数据进行分析。有时候,经常也需要将这个参数设置为false,放弃安全管理
posted @ 2008-07-23 10:30 zengjun 阅读(131) | 评论 (0)编辑
在网络开发中,经常遇到需要使用ASP.NET与JavaScript联合进行控制的情况。在本篇中,将使用DataGrid进行数据绑定,使用Javascript控制当选中其中的checkbox时,该行颜色改变。
  首先,在页面中创建一个DataGrid控件,并设置其模板。
  以下是引用片段:
  < asp:DataGrid id="DataGrid1" runat="server" AutoGenerateColumns="False">
     < Columns>
        < asp:TemplateColumn>
           < ItemTemplate>
               < asp:CheckBox id="checkbox1" Runat ="server">< /asp:CheckBox>
               < asp:Label runat="server" Text='< %# DataBinder.Eval(Container, "DataItem") %>'>< /asp:Label>
           < /ItemTemplate>
        < /asp:TemplateColumn>
     < /Columns>
  < /asp:DataGrid>

  第二,在页面中的< head>< /head>中编写JavaScript脚本函数,进行CheckBox的判断和颜色改变的控制。
  以下是引用片段:
   < script>
       function checkme(obj,tr){
           if(obj.checked)
              tr.style.backgroundColor='blue';
          else
              tr.style.backgroundColor='';
      }
  < /script>

  第三,在Page_Load事件中为DataGrid绑定数据,并关联CheckBox的JavaScript脚本。
以下是引用片段:
   private void Page_Load(object sender, System.EventArgs e)
  {
  // Put user code to initialize the page here

  if(!IsPostBack)
  {

  databind();

  }

  }

  private void databind()

  {

  ArrayList arr=new ArrayList();

  arr.Add("新闻综合");

  arr.Add("综艺");

  arr.Add("电影");

  arr.Add("教育");

  arr.Add("戏剧");

  arr.Add("军事");

  arr.Add("体育");

  DataGrid1.DataSource=arr;

  DataGrid1.DataBind();

  int i;

  for(i=0; i< DataGrid1.Items.Count; i++){

  CheckBox cb;

  cb=(CheckBox)DataGrid1.Items[i].FindControl("checkbox1");

  DataGrid1.Items[i].Attributes.Add("id","tr" + i.ToString());

  cb.Attributes.Add("onclick","checkme(this,tr" + i.ToString() + "); ");

  }

  }
  第四,完成之后运行程序。程序运行后,会在DataGrid控件的每行前显示一个CheckBox控件,选择该控件,该行背景颜色变蓝色,取消选择,该行颜色恢复初始状态。
posted @ 2008-07-17 09:11 zengjun 阅读(30) | 评论 (0)编辑
js获取浏览器高度和宽度值

网页可见区域宽: document.body.clientWidth
网页可见区域高: document.body.clientHeight
网页可见区域宽: document.body.offsetWidth (包括边线的宽)
网页可见区域高: document.body.offsetHeight (包括边线的高)
网页正文全文宽: document.body.scrollWidth
网页正文全文高: document.body.scrollHeight
网页被卷去的高: document.body.scrollTop
网页被卷去的左: document.body.scrollLeft
网页正文部分上: window.screenTop
网页正文部分左: window.screenLeft
屏幕分辨率的高: window.screen.height
屏幕分辨率的宽: window.screen.width
屏幕可用工作区高度: window.screen.availHeight
屏幕可用工作区宽度: window.screen.availWidth

 

注意在XHTML标准下一个请将body改成documentElement

posted @ 2008-07-05 10:55 zengjun 阅读(545) | 评论 (0)编辑

让控件获取焦点及设置输入法全角半角或无效

做开发的过程中,常遇到一些页面要求光标的默认位置固定在某控件上
看起来好像很难,其实实现方法很简单.
JavaScript里面有现成的设置焦点的方法
可以写一个简单的函数命名为setFocus,然后在Page_Load里调用就可以了
比如需要设置焦点的是mytextbox控件
那么只要Page_Load写上Call setFocus(Me.mytextbox)就可以了
下面是VB.NET代码实例.C#的代码也差不多...


   Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
       Call setFocus(Me.txt_code)
       End Sub

 

   Private Sub setFocus(ByVal ctrl As Control)
       Dim script As String
       script = "<script language='JavaScript'>" & _
                "        document.getElementById('" & ctrl.ClientID & "').focus();" & _
                "</script>"
       RegisterStartupScript("setfocus", script)
   End Sub


下面是输入法设置,更简单:

      Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
       If Not Page.IsPostBack Then
           'IME半角設定
           setIME(Me.Page, Me.txt_code, 1)
           setIME(Me.Page, Me.txt_date, 1)
       End If
       End Sub

 


   Public Sub setIME(ByRef pgTemp As Page, _
                     ByRef ctrTemp As WebControl, _
                     ByVal intMode As Integer)
       Select Case intMode
           Case 0 'IME無効
               ctrTemp.Attributes.Add("style", "ime-mode:disabled")
           Case 1 'IME半角
               ctrTemp.Attributes.Add("style", "ime-mode:inactive")
           Case 2 'IME全角
               ctrTemp.Attributes.Add("style", "ime-mode:active")
           Case 3 'IME自動
               ctrTemp.Attributes.Add("style", "ime-mode:auto")
           Case 4 'IME無効且右对齐
               ctrTemp.Attributes.Add("style", "ime-mode:disabled;text-align:right")
           Case 5 'IME半角且右对齐
               ctrTemp.Attributes.Add("style", "ime-mode:inactive;text-align:right")
       End Select
   End Sub

posted @ 2008-04-12 09:54 zengjun 阅读(213) | 评论 (0)编辑

调用C++开发的DLL报内存异常错误

问题:  
  最近开发的一个项目中使用了C++开发的一个MD5加密动态库,调用加密时传入的参数类型(string)不适合C++导致内存异常(虽然是偶尔出错,却导致IIS进程重启或退出)。现在修改传入参数类型为StringBuilder问题解决,现在发贴出来希望对遇到此问题的朋友有所帮助(这问题可把我给整惨了!)

原来的代码:
[DllImport("md5.DLL",CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern void MD5ToStr(string inStr, int len, ref string outStr);

修改后的代码:
[DllImport("md5.DLL",CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
        public static extern void MD5ToStr(StringBuilder inStr, int len, ref StringBuilder outStr);

 

以下是在C++中的源码:
MD5DLL_API void MD5ToStr( const unsigned char* inStr, int inLen, char** outStr)
{
 unsigned char result[16];

 MD5_CTX context;
 
 MD5Init (&context);
 MD5Update (&context, (unsigned char*)inStr, inLen);
 MD5Final ( result, &context);

 BCD( result, 16, *outStr);
}

posted @ 2008-04-08 15:10 zengjun 阅读(55) | 评论 (0)编辑

DataFormatString
DataFormatString 属性语法如下:

DataFormatString="{0:格式字符串}"

我们知道在DataFormatString 中的 {0} 表示数据本身,而在冒号后面的格式字符串代表所们希望数据显示的格式;另外在指定的格式符号后可以指定小数所要显示的位数。例如原来的数据为「1.56」,若格式设定为 {0:N1},则输出为「1.5」。其常用的数值格式如下表所示:

格式字符串 输入 结果
"{0:C}" 12345.6789 $12,345.68
"{0:C}" -12345.6789 ($12,345.68)
"{0:D}" 12345 12345
"{0:D8}" 12345 00012345
"{0:E}" 12345.6789 1234568E+004
"{0:E10}" 12345.6789 1.2345678900E+004
"{0:F}" 12345.6789 12345.68
"{0:F0}" 12345.6789 12346
"{0:G}" 12345.6789 12345.6789
"{0:G7}" 123456789 1.234568E8
"{0:N}" 12345.6789 12,345.68
"{0:N4}" 123456789 123,456,789.0000
"Total: {0:C}" 12345.6789 Total: $12345.68

其常用的日期格式如下表所示:

格式 说明 输出格式
d 精简日期格式 MM/dd/yyyy
D 详细日期格式 dddd, MMMM dd, yyyy
f 完整格式 (long date + short time) dddd, MMMM dd, yyyy HH:mm
F
完整日期时间格式
(long date + long time)
dddd, MMMM dd, yyyy HH:mm:ss
g 一般格式 (short date + short time) MM/dd/yyyy HH:mm
G 一般格式 (short date + long time) MM/dd/yyyy HH:mm:ss
m,M 月日格式 MMMM dd
s 适中日期时间格式 yyyy-MM-dd HH:mm:ss
t 精简时间格式 HH:mm
T 详细时间格式 HH:mm:ss

posted @ 2008-03-18 15:40 zengjun 阅读(32) | 评论 (0)编辑

前面从架构方面介绍了petshop怎样通过工厂模式可以轻松替换持久层实现。这次简单说一说petshop的表现层实现。

       petshop的表现层使用了Web 页面(aspx)和用户控件(ascx)控件及自定义服务器控件等ASP.NET技术。

       web页面(aspx)是用户和服务器交互的接口,也是用户除静态页面外唯一能够访问到的asp.net组件,其他像用户控件(ascx)和服务器控件只能在web页面(aspx)中使用,用户不能直接访问。用户控件类似于web页面,服务器控件与jsp的标签相似,可以在比较中进行学习。

一.用户控件和服务器控件。

1.用户控件。

       用户控件与web页面极为相似,只不过是以ascx后缀命名(确保用户控件不能作为独立 Web 窗体页来运行),并且不能包含 <HTML>、<BODY> 和 <FORM> 元素,这些元素必须位于宿主页中。用户控件使您能够很容易地在多个 ASP.NET Web 应用程序之间划分和重复使用公共用户界面 (UI) 功能。asp.net页面中也可以使用include,也就是服务器端包含(SSI),不过用户控件编译后是.net 框架中的UserControl 类的实例,可以通过编程方式操作用户控件,通过访问由 ASP.NET 提供的对象模型支持,具有更大的灵活性。

       用户控件使用小结:

  (1)用户控件使开发人员能够使用编写WEB窗体页的相同编程技巧轻松地定义自定义控件。 作为约定,用.ascx文件扩展名指示这样的控件。这样可以确保用户控件文件不能作为独立的WEB窗体页执行。

  (2)用户控件通过Register指令包括在另一WEB窗体页中,该指令指定TagPrefix、TagName和Src location。

  (3)注册了用户控件后,可以像普通的服务器控件那样将用户控件标记放置在WEB窗体页中(包括runat="server"属性)。在包含WEB窗体页中将用户控件的公共字段、属性和方法提升为该控件的公共属性(标记属性)和方法。

  (4)用户控件参与每个请求的整个执行生存期,并且可以处理自己的事件,封装来自包含WEB窗体页的一些页逻辑。

  (5)用户控件不应包含任何窗体控件,而应依靠其包含WEB窗体页在必要时包括窗体控件。

  (6)可以使用System.WEB.UI.Page类的LoadControl方法以编程方式创建用户控件。用户控件的类型由ASP.NET运行库决定,遵循约定文件名_扩展名。

  (7)只有当为用户控件包括了Register指令时,用户控件的强类型才能由包含WEB窗体页使用(即使没有实际声明的用户控件标记)。 

2.服务器控件。

       asp.net服务器控件是一种类似于jsp taglib的编程模型。我们可以通过编程方式创建控件,然后在页面中使用。服务器控件可以提供极为强大的功能。ms为asp.net提供了三种服务器控件:

       HTML 服务器控件   对服务器公开的 HTML 元素,可对其进行编程。HTML 服务器控件公开一个对象模型,该模型十分紧密地映射到相应控件所呈现的 HTML 元素。

       Web 服务器控件   这些控件比 HTML 服务器控件具有更多内置功能。Web 服务器控件不只包括窗体类型的控件,例如按钮和文本框;而且还包括特殊用途的控件,例如日历。Web 服务器控件与 HTML 服务器控件相比更为抽象,因为其对象模型不一定反映 HTML 语法。

       验证控件   包含逻辑以允许测试用户输入的控件。将一个验证控件附加到输入控件,测试用户对该输入控件输入的内容。验证控件可用于检查必填字段,对照字符的特定值或模式进行测试,验证某个值是否在限定范围之内以及其他目的。

.net2.0更是大大加强了web服务器控件。另外我们可以创建自定义的服务器控件(由于创建自定义控件相对复杂,并且内容较多,所以以后有时间介绍。),以提供通用控件没有提供的功能。

3.Web 用户控件和Web 自定义控件的比较:

Web 用户控件:

易于创建

为使用可视化设计工具的使用者提供有限的支持

每个应用程序中需要控件的一个单独副本

不能添加到 Visual Studio 中的工具箱

适用于静态布局

 

Web 自定义控件:

难于创建

为使用者提供完全的可视化设计工具支持

仅在全局程序集缓存中需要控件的单个副本

可以添加到 Visual Studio 中的工具箱

适用于动态布局

 

二.petshop的表现层实现简介

1.App_Code目录

App_Code下包含了用户自定义的服务器组件,用于流程控制的业务逻辑类,和Utils类,另外还有页面Page和应用Application的配置类。

       Default.aspx.cs 是一个System.Web.UI.Page,主要注册了load事件处理器,this.Load += new System.EventHandler(this.Page_Load);好像没有使用,不太清楚。

       Global.asax.cs 是一个HttpApplication,主要重写了应用出错方法,protected void Application_Error(object sender, EventArgs e),将错误信息记入windows日至。同时通过重载GetVaryByCustomStritom属性。

       controls目录下包含两个自定义服务器控件,SimplePager和ViewStatePager,它们都是用于分页的。SimplePager继承自Repeater,ViewStatePager又继承自SimplePager,所以他们都是模版可迭代控件。它们通过装饰模式为Repeater中的模版添加了分页按钮,并提供事件接口,用户可以注册onpageindexchanged事件处理器,该处理器主要用于绑定数据源。分页控件和我们emed3.0的分页标签不同,它绑定了所有的数据,但只显示特定也的数据。ViewStatePager通过viewstate维护分页状态,可以在一个页面中同时存在多个分页控件。

       ProcessFlow目录下的类用于控制业务流程。AccountController.cs导航和用户帐户有关的事件。通过业务逻辑层(BLL)处理用户登录登出,获取用户信息,更新用户信息等逻辑。CartController.cs通过业务逻辑层(BLL)处理购物车相关信息的逻辑,比如创建,购买,添加购物,获取或存储订单地址信息等逻辑。

       WebComponents下包含CleanString.cs Utils类,处理传入的字符串数据,保证不会超过maxLength长度,如果传入的是空(null或trim后是“”),返回“”,其他换码,并将单引号去掉,替换为空格。

2.Controls目录

Controls目录下存放了用户控件。

       addressui.ascx 封装了用户地址信息的一个table,用于收集和显示地址信息。

       Banner.ascx 横幅,封装了页脚。

       navbar.ascx 导航条,其中包含页眉,页眉下的登录,登出,帐户信息和查询栏还有帮助链接。最下面是一个导航菜单,分别导航到不同种类的动物。

       preferences.ascx 封装了用户的喜好特性的信息页面组件。

       其他控件作用相似,都是封装了某一个相对独立的UI界面的一部分。

3.Images目录 

       当然是包括了web页面用到的图片。

4.根目录

       根目录下的其他文件是aspx页面和web.config配置文件和Styles.css样式文件。

       Default.aspx是主页面(index),使用了页的顶部使用navbarnomenu控件和Banner控件。,中间是一个表,表左边是连接导航,中间是地图导航。点链接后会导航到Category.aspx。

       Category.aspx 用于显示某一类别的动物的信息。使用了SimplePager服务器控件。

       其他还有SignIn.aspx用户登录,MyAccount.aspx用于查看和编辑个人账户信息,Search.aspx用于搜索,ShoppingCart.aspx显示购物车中的信息等。

 

三.petshop的页面布局

       petshop的布局比较简单,是通过组合用户控件实现的。对于Default.aspx页的顶部使用navbarnomenu控件,中间通过表table布局,页脚使用Banner控件。对于Category.aspx页顶部使用navbar控件,主体使用SimplePager自定义服务器控件。对于Search.asp和其他页面与Category.aspx几乎一样。

 

四.petshop的页面导航

       在主页面上可以导航到各个类别,导航到各个类别或者某类中的具体动物时,还可以通过navbar,随时导航到各个类别。

       所有存在搜索的页面都是通过navbar.ascx用户控件中的<form id="search" method="get" action="Search.aspx">导航的。

       主页面default.aspx通过 href="Category.aspx?categoryId=BIRDS"连接将用户导航到具体的物种列表。

       在navbar.ascx中,通过<a href="SignOut.aspx" >,<a href="EditAccount.aspx">,<a href="ShoppingCart.aspx">,<a href="SignIn.aspx">分别导航到登出,编辑个人帐户信息,购物

车,和登录页面。

       在Category.aspx中<form id="form" method="post" runat="server">,请求到该页面时SimplePager自定义控件会调用Category.aspx.cs的protected void PageChanged(object sender, DataGridPageChangedEventArgs e)方法,通过Request["categoryId"]获取该类动物的列表。并构造单独动物的链接--<A href='Items.aspx?productId=<%# DataBinder.Eval(Container.DataItem, "Id") %>'>,通过动物id,获取动物的详细信息。  

       对于SignIn.aspx,如果用户没有账号,可以通过<a href="CreateAccount.aspx">导航到<a href="CreateAccount.aspx">。用户点击登录按钮会触发SignIn.aspx.cs的SubmitClicked()事件处理器方法,该方法通过ProcessFlow.AccountController 处理登录请求,如果登录成功导航到合适的页面,HttpContext.Current.Response.Redirect(URL_ACCOUNTSIGNIN, true)--主页面或HttpContext.Current.Response.Redirect(FormsAuthentication.GetRedirectUrl(userId, false), true)--其他页面。

       其他页面的原理差不多,也就是一部分导航是直接通过<a>标签写在页面中,另一部分是通过ProcessFlow中的导航逻辑类进行按照逻辑和操作状态导航(利用HttpContext.Current.Response.Redirect)。

 

五.petshop的应用和会话状态

       petshop使用基于Form的认证模式:

              <authentication mode="Forms">

                     <forms name="PetShopAuth" loginUrl="SignIn.aspx" protection="None" timeout="60"/>

              </authentication>

       其他的location定义了拒绝匿名访问的页面,点击这些页面时,用户如果没有登录系统会首先转到登录页面。

       用户信息和用户的购物信息基本上是通过ProcessFlow中的AccountController.cs和CartController.cs实现的。

       用户登录时会调用AccountController.cs的public bool ProcessLogin(string userId, string password)方法,登录成功后会通过HttpContext.Current.Session[ACCOUNT_KEY] = myAccountInfo在session中储存用户帐号信息。创建新帐号成功后同样会在session中储存用户帐号信息。同理,更新帐户信息会更新session,退出会清除session。

 

       对于购物信息,也是存在于session中。存储购物车后会将购物车信息储存在session中。存储信用卡时会在session中保存信用卡信息,等等,不一一介绍了。

posted @ 2008-03-03 17:49 zengjun 阅读(67) | 评论 (0)编辑

有很多朋友对.NET三层和N层结构不是很清楚,我把以前研究三层经典架构PetShop的文档整理了一下,希望对大家有些帮助,另我做了个PDF,有需要的请留下邮箱,有时间逐一发送。

petshop是C#实现的petstore,具体和技术无关的情况就不多介绍了。
petshop3.0比petshop1和2都有了较大的改变,主要是设计方面的。看一下里面的8个工程和1个站点就知道它肯定分了不少层。
一.概况介绍。
Model:
模型层,封装业务实体,一般和数据库模式对应。
例如:
       public class AccountInfo {
 
              // Internal member variables
              private string _userId;
              private string _password;
              private string _email;
              private AddressInfo _address;
              private string _language;
              private string _category;
              private bool _showFavorites;
              private bool _showBanners;
              。。。
       }
IDAL:
数据访问接口层,主要是一些dao接口。
例如:
       public interface IAccount
       {
              AccountInfo SignIn(string userId, string password);
              AddressInfo GetAddress(string userId);
              void Insert(AccountInfo account);
              void Update(AccountInfo Account);
       }
 
OracleDAL:
oracle实现的数据访问层。
 
SQLServerDAL:
sql实现的数据访问层。
OracleDAL和SQLServerDAL中的类都实现了IDAL中的接口。属于dao实现。
 
DALFactory
负责确定是使用oracle实现还是mssql实现。通过在web.config中的配置确定使用哪一个dal实现(通过反射,动态生成访问类是PetShop.SQLServerDAL还是PetShop.OracleDAL命名空间中的类)。
              <add key="WebDAL" value="PetShop.SQLServerDAL"/>
              <add key="OrdersDAL" value="PetShop.SQLServerDAL"/>
       public class Account
       {
              public static PetShop.IDAL.IAccount Create()
              {                  
                     /// Look up the DAL implementation we should be using
                     string path = System.Configuration.ConfigurationSettings.AppSettings["WebDAL"];
                     string className = path + ".Account";
 
                     // Using the evidence given in the config file load the appropriate assembly and class
                     return (PetShop.IDAL.IAccount) Assembly.Load(path).CreateInstance(className);
              }
       }
 
BLL:
业务访问层。通过DALFactory,读取配置,决定使用何种dal实现。
       public class Account {         
              public AccountInfo SignIn(string userId, string password) {
 
 
                     if ((userId.Trim() == string.Empty) || (password.Trim() == string.Empty))
                            return null;
 
                     // 通过DALFactory调用具体的dal实现。
                     IAccount dal = PetShop.DALFactory.Account.Create();
 
                     // Try to sign in with the given credentials
                     AccountInfo account = dal.SignIn(userId, password);
 
                     // Return the account
                     return account;
              }
              。。。
}
 
Web:
表现层,主要包括了Web 页面(aspx)和用户控件(ascx)控件及自定义服务器控件SimplePager和ViewStatePager。
 
Utility:
公用模块,一组帮助器类,其他业务层和数据访问层可能会使用到的一些公用方法。
 
 
 
 
分层如何使系统更灵活
       学习面向对象设计和设计模式和架构模式,我们可以知道,设计的重要目的,一个是可重用,一个是可维护还有就是可扩展性。
       面向对象技术本身就提供了很多可重用得机制,通过继承和组合可以使代码较大程度的重用。另外,我们需要通过设计,抽象出基本的概念,对这些概念进行重用。重用可以提高系统的可维护性,因为重用的东西一般经过了充分的测试和长时间的考验,比我们自己重复发明的轮子的质量更容易保证。
可扩展,继承和重载是扩展的方式,但他们是语言级的,我们需要通过设计达到系统级的可扩展。
这里主要结合petshop的分层设计和实现谈一下这几个设计的指标。
       上面介绍了各个层,各层的调用关系是这样的:
web层-->BLL(使用Model)-->DALFactory(通过IDAL)-->具体DAL实现层(oracle或ms sql)-->持久存储。
       这样,各层至于相邻的层交互,通过定义良好的接口,层内部的实现对其他层来说关系是不大的。这很符合软件工程的思想,因为定义好了接口后,开发人员就可以按照自己的特长实现各自的层,并且容易测试,因此可以提高软件的开发效率和开发质量。
从架构和源码实现上我们可以看到,数据层的灵活性,可扩展性和可维护性是通过DALFactory层实现的。我们知道,由于采用面向接口编程这一原则,DALFactory可以通过配置文件信息来确定使用哪一个IDAL实现,这样我们就可以在部署时通过修改配置文件来适应客户的数据库要求。当然这也要求,具体的数据库实现层要遵循特定的命名约定,比如对于Account实现,sql和oracle中对应的类要有相同的名字和构造函数(现在是必须有默认构造函数,否则无法初始化),当然所在的名称空间要不同。
以后,当我们需要实现mysql或db2的数据实现层的时候,我们只需要通过mysql或db2按照上面的命名约定实现,在web.config文件中进行配置就可以了(可扩展和可维护性)。而且,如果客户原先使用mssql后来要使用oracle,然后…… 如此反复的折腾,我们也不会挠头,因为我们原先的实现可重用,新的要求,可扩展。另一方面,对于同一个数据库我们也可以采用不同的实现方法,比如ado.net(又分为直接的sql和存储过程实现),orm框架,ibati式的半orm框架,我们可以为每种这样的实现建立一个工程,灵活的选择,而不是仅在原来的基础上修改。这就是petshop数据访问层向我们展示的为什么要这么分层。
       其实现在的很多框架和系统为了实现灵活性都是通过配置实现的,因为修改配置
不像修改源代码那样需要重新发布,而且就像petshop,OracleDAL,SQLServerDAL的两个dll可以同时存在,需要使用哪一个就配置哪一个就可以了。

posted @ 2008-03-03 17:48 zengjun 阅读(86) | 评论 (5)编辑