如何在netweb中让数据树形显示

xierfly 2008-09-22 10:55:45
目前遇到一个问题,就是让用户的留言数据分级显示,并且,其他用户可以针对某一用户的留言再进行留言;比如:

留言者:A:文章不错哦。
留言者:B:A 你认为这文章很好吗?
留言者:C:B 你认为这文章不好吗?

差不多就是这样的格式了,请知道的朋友提供点示例或指点一下。谢绝空谈的
...全文
83 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
mengxj85 2008-09-23
  • 打赏
  • 举报
回复
动态输出HTML代码,根据条件在HTML中加入空格,这个方法应该可以吧,个人的想法,不过应该有更好的方法
lfywy 2008-09-23
  • 打赏
  • 举报
回复
其实1楼的小姐说的是又道理,不过只是点水蜻蜓,需要你自己去体会延伸概念的!
1.我觉得可以动态控制HTML中的TABLE,你可以给每行的的TR做标记,当然这是为下面的留言做铺垫以及是哪个的留言,可以用AJAX实现无刷新更好看。
2.你要的要求都是可以实现的,每个留言错位,其实只是在前面加一个固定长度的一列,就是1楼小姐说的空格,根据你发表的,在后台处理代码发回HTML段,控制TR减少还增加是可行的!
3.以上的要求你必须知道AJAX和Table的详细操作,网上又很多列子!
最终个人结论:这个很简单,因为有合理的逻辑就是可以做出来的!
wolfsky1994 2008-09-23
  • 打赏
  • 举报
回复
A的留言:1000
B给A的留言:10001000
C给A的留言:10001001
D的留言:1001
wolfsky1994 2008-09-23
  • 打赏
  • 举报
回复
数据库设计的时候加入分级的字段设计
1000
10001000
10001001
100010001001
1001
根据层次的定义控制输入和输出
xierfly 2008-09-23
  • 打赏
  • 举报
回复
谢谢楼上的朋友,
但是我要的不是说空格的问题,而是让留言有层次感,可以对留言者说的话再进行留言。
ExtAspNet v2.2.1 ExtAspNet是一组专业的Asp.net控件库,拥有原生的AJAX支持和丰富的UI效果, 目标是创建没有JavaScript,没有CSS,没有UpdatePanel,没有WebServices的Web应用程序。 支持的浏览器: IE 7.0+, Firefox 3.0+, Chrome 2.0+, Opera 9.5+, Safari 3.0+ 注:ExtAspNet基于一些开源的程序ExtJS, HtmlAgilityPack, Nii.JSON, YUICompressor。 示例: http://extasp.net/ 开源: http://extaspnet.codeplex.com/ 博客: http://sanshi.cnblogs.com/ 邮箱: sanshi.ustc@gmail.com 发布历史: +2010-03-28 v2.2.1 +为TabStrip的GetAddTabReference函数增加重载方法,以便指定Tab的图标(feedback:mmdcup)。 -修正此函数通过PageContext.RegisterStartupScript调用时不能正确显示Icon的BUG(feedback:zhaowenke)。 -修正basic/hello.aspx示例在单独浏览器打开后,不能弹出对话框的BUG。 -隐藏示例首页最外层RegionPanel的边框ShowBorder="false"。 +集成Extjs最新版本v3.1.1。 -增加一个新的Theme - Access。 -修正了Firefox下Zoom In/Out时页面消失的BUG。 -删除Panel的EnableLightBackgroundColor属性,同时EnableBackgroundColor只支持Blue和Gray两种Theme。 +2010-01-31 v2.2.0 -使得Asp.net的控件ImageButton具有和Asp.net的Button控件类似的行为(Ajax提交)(feedback:261629698)。 +TabStrip增加GetAddTabReference和GetRemoveTabReference两个函数,用来向TabStrip控件动态增加删除Tab。 -增加示例tabstrip/tabstrip_addtab.aspx。 -重构了示例网站的架构,目前只有一层IFrame结构。 -为TabStrip增加EnableTabCloseMenu属性,是否启用右键菜单,可用来关闭当前Tab和所有其他Tab。 -为NumberBox增加DecimalPrecision属性,用来控制小数点后的位数(需要设置NoDecimal="false")(feedback:zqmars)。 -Window控件更新。 -关闭按钮默认直接关闭,不会弹出确认对话框。 -GetConfirmFormModifiedHideReference的函数的ConfirmFormModified简化为Confirm,所以此函数更名为GetConfirmHideReference。 -增加两个属性EnableConfirmOnClose(默认false),CloseAction(Hide, HideRefresh, HidePostBack)。 -修正EnableMaximize属性不能使Window最大化的BUG,修正了双击标题栏不能最大化的BUG。 -删除Button控件的SystemIcon属性,比如以前这样定义SystemIcon="Close",现在需要这样定义Icon="SystemClose"。 -WindowPosition默认居,而不是黄金分割位置。 +Button, Window等控件弹出位置属性的变化。 -Window的Target属性由字符串类型变为枚举类型,注意更新以前的代码:Target="_self" -> Target="Self", Target="_parent" -> Target="Parent"。 -MenuButton, LinkButton, Button, LinkButtonField的ConfirmTarget属性由字符串变为枚举类型,可以取三个枚举值Self, Parent, Top。 -Confirm.GetShowReference的最后一个参数target变为枚举类型。 -Alert.GetShowReference的showInParent参数也变为Target枚举类型。 -MenuButton, LinkButton, Button, LinkButtonField增加ValidateTarget用来控制表单验证失败时提示对话框的显示位置。 +2010-01-06 v2.1.9 -集成Extjs最新版本v3.1.0。 -修正灰色皮肤的CSS问题。 -修正Grid的列名不能包含文字符的BUG(feedback:davidwen)。 -为Web.config和PageManager增加属性AjaxTimeout(单位秒,默认30秒)。 -修正了在Grid的PageIndexChange事件不能获取SelectedRowIndexArray属性的BUG(feedback:Violet)。 -Button控件将不再自动拥有display:inline属性,如果希望两个按钮在一行显示,请为第一个按钮设置CssStyle="float:left;"属性。 -修正了弹出菜单的位置在Firefox下不正确的BUG(feedback:eroach)。 -为TriggerBox和TwinTriggerBox增加EnableEdit属性。 -使用Hidden来显示隐藏ExtAspNet控件,而不是使用Visible属性(Visible目前设置为只读属性)。 -使用Hidden控制Window控件的显示隐藏,Popup已经标记为Obsolete属性。 -Window的实例方法GetCloseReference等以及ActiveWindow的静态方法GetCloseReference等,其的Close全部改为Hide。 -增加TabStripTab控件可关闭属性EnableClose(默认为false)以及两个方法GetShowReference和GetHideReference(feedback:anson)。 -修正绑定到Tree的XMLDocumentIcon属性映射错误(feedback:nopnop9)。 -修正HtmlEditor不能编辑的BUG(feedback:TheBox)。 -修正IE下有时会出现空白页面的情况(feedback:olivia919)。 +2009-12-06 v2.1.8 -修正了使用IFrame的Window关闭后不能再次打开的BUG(feedback:alexa99)。 -修正了IE下Grid的一个JS问题(feedback:lqm4108)。 -修正Alert消息引号未编码导致的JS错误(feedback:sun1299shine)。 +集成extjs3.0.3。 -修正弹出对话框的宽度计算错误(会保持最小的状态)。 -增加新的皮肤Gray。 -为示例工程添加改变语言和皮肤的下拉列表。 -为PageContext增加静态函数Refresh,在切换语言和皮肤时使用。 +2009-12-01 v2.1.7 -增加示例(iframe/parent_postback_run3.aspx),如何通过简单的Javascript代码回发父页面(feedback:eroach)。 -修正一些书写错误(feedback:bmck)。 -从Region控件删除SplitColor属性,增加CollapseMode, EnableSplitTip, SplitTip, CollapsibleSplitTip属性(feedback:bmck)。 -BorderPanel更名为RegionPanel。 -DropDownList拥有MarkInvalid方法(feedback:sun1299shine)。 -增加国的省市县三级联动示例(data/shengshixian.aspx)(feedback:Blues T)。 -修正了使用IFrameUrl的Tab在切换过程会重复加载的问题,这是一个在v2.1.6引入的问题(feedback:eroach)。 -修正了启用AutoPostBack的Grid,其RowClick会覆盖LinkButtonField, HyperLinkField, CheckBoxField的点击事件(feedback:yymaoji)。 +2009-11-26 v2.1.6 +修正动态创建Grid列的BUG(feedback:gxpan)。 -增加示例(data/grid_dynamic_columns.aspx)。 -修正Form不能自适应浏览器大小的改变(feedback:kaywood)(WorkItem#6309)。 -增加重载方法Alert.Show(message, title, icon)(feedback:TheBox)(WorkItem#6353)。 -为容器控件(比如Panel,Region,Tab等)增加AJAX属性IFrameUrl(feedback:BluesT)。 -重新设计模拟树的下拉列表的实现,避免选某项后的闪烁。 +2009-11-21 v2.1.5 +Tree优化。 -修正Expanded项和Checked项的状态在回发改变后不能保持的BUG。 -GetNodeById更名为FindNode,保持和FindControl一致命名。 -删除CheckedNodeIDArray属性,增加GetCheckedNodes和GetCheckedNodeIDs函数。 -删除ExpandedNodeIDArray属性,增加GetExpandedNodes和GetExpandedNodeIDs函数。 -增加示例(data/tree_select_run.aspx),如何选当前节点的所有子节点(feedback:wjl_wjl520)。 +TreeNode的属性NodeId被重命名为NodeID,这是ExtAspNet的一个命名约定。 -同时更名的还有GridColumn的ColumnId->ColumnID,GetColumnId->GetColumnID。 -Grid1.Columns.FindColumnById函数被Grid1.FindColumn所替代。 -为TreeCheckEventArgs,TreeExpandEventArgs,TreeCommandEventArgs增加Node属性。 -为所有控件增加Focus(覆盖Control默认的Focus函数)和GetFocusReference函数。 -增加示例(other/custom_postback.aspx)(feedback:thebox)。 -如何自定义Javascript脚本和C#处理函数来响应键盘事件。 -为Tree增加AutoLeafIdentification属性。 -增加示例(tree_auto_leaf_identification.aspx)(feedback:wdrabbit)。 +2009-11-17 v2.1.4 -修正Window的关闭按钮提示信息一直是文的BUG(feedback:thebox)。 -部分ExtAspNet控件的设计时支持(会在后续版本逐步完善)。 -v0.2beta2版本关于PersistChildren(true)的描述有误,这个是设计时属性,和运行时是否保持状态没有关系。 -修正CheckBox控件的CheckedChanged事件会被触发两次的BUG(Data PostBack->AutoPostBack, Event PostBack->EnablePostBack)。 -为TextBox,TextArea,DatePicker,NumberBox,TriggerBox等控件增加AutoPostBack属性(feedback:dk3214)。 +为表单字段增加RequiredMessage,MaxLengthMessage,MinLengthMessage属性,用于指定验证失败时提示信息。 -为空则使用默认的提示信息,默认的提示信息支持多语言,建议一般情况下使用默认信息。 +为表单字段增加MarkInvalid和GetMarkInvalidReference函数(feedback:sun1299shine)。 -增加示例:form/form_validate.aspx +2009-10-19 v2.1.3 +增加支持在AJAX时改变的控件属性列表(/ajax.aspx)。 -ExtAspNet支持原生的AJAX,也就是说控件的属性改变在AJAX过程会反映到页面,但并不是所有的控件属性都支持AJAX改变。 -加载s.gif图片在本机进行,不会请求extjs.com远程资源(feedback:efrigate43,abaocoole)。 -在AJAX回发后确保Asp.net的按钮控件仍然具有AJAX的特性。 -更新/basic/login.aspx示例,使用验证图片(feedback:kedee)。 -为Grid增加AutoPostBack属性和RowClick事件,示例在/data/grid_autopostback.aspx(feedback:chenguizhu2006)。 -为所有的表单字段增加AJAX属性ReadOnly(feedback:skydb)。 -GridTemplateField生成到页面控件具有唯一ID,例如Grid1_ct5_Label2,Grid1_ct6_Label2(feedback:geruger)。 +2009-09-27 v2.1.2 -为Tree控件增加GetExpandAllNodesReference和GetCollapseAllNodesReference两个函数。 -修正RELEASE版本下多语言加载的BUG(feedback:yigehaoren)。 -增加pt_BR语言,由Ujvari提供。 +为所有Panel(包括Grid,Tree,Form等)增加枚举类型Icon,其包含1700多个小图标。 -如果Panel具有IconUrl属性,则IconUrl优先于Icon。 -所有Icon的列表在icon.aspx。 -为Button,MenuItem(MenuButton,MenuHyperLink),AccordionLink,TreeNode,Image(如果ImageUrl为空,则取Icon的值)增加Icon属性。 +2009-09-15 v2.1.1 -修正不能动态修改AccordionPane属性Items的BUG。 +为Button, MenuButton, LinkButton, LinkButtonField增加ConfirmTarget。 -如果需要在父页面弹出确认对话框,需要设置ConfirmTarget="_parent"(类似Window控件的Target="_parent")。 +为ExtAspNet.Alert.Show增加点击确定的JavaScript回调函数。 -一个典型应用,在Window控件打开新页面,如果传递的参数不正确,则首先提示参数不对然后关闭此弹出窗口。 -ExtAspNet.Alert.Show("参数错误!", String.Empty, ExtAspNet.ActiveWindow.GetCloseReference()); +TreeNode的前面的多选框可以自动回发了。 -为TreeNode增加AutoPostBack属性,增加事件数据类TreeCheckEventArgs,为Tree增加事件NodeCheck。 -示例在:http://extasp.net/data/tree_run.aspx -Grid增加GetNoSelectionAlertInParentReference函数,用来表示没有选任何一项时在父页面弹出对话框的JS代码。 -修正IE7下不能以下划线作为CSS类名的前缀的BUG(feedback:Steve.Wei)。 -添加定时器控件Timer,用来定时发起AJAX请求。 +2009-09-06 v2.1.0 -Button的Pressed属性值能够正确的反映客户端的变化。 -优化Tree控件的AJAX实现。 +为页面的Form添加autocomplete="off"属性。 -参考http://www.cnblogs.com/sanshi/archive/2009/09/04/1560146.html#1635830 +添加对extjs3.0所有语言的支持。 -ExtAspNet扩展的多语言包在js\languages\extaspnet目录下,目前只有en,zh_CN,zh_TW三种实现 -你可以向其添加自己的语言版本,并执行js\languages下的pack.bat打包,最后编译工程。 +2009-09-01 v2.0.9 -为ExtAspNet.Alert添加两个静态方法ShowInParent和GetShowInParentReference,用于在父页面弹出窗口。 +在aspx页面必须显示的声明控件的集合属性(比如Tabs(TabStrip), Items(PanelBase), Nodes(TreeNode))。 -这将会影响所有的aspx页面,所以要特别关注。 -重命名AccordionPanel为AccordionPane (这也是在Asp.net AJAX使用的名称). +所有的面板默认有两个集合属性(Toolbars和Items). -尽管TabStrip, From, Tree, Accordion继承了Items属性,但是你并不能对其设置(此时Items是只读的). -这将会影响所有的aspx页面,一定要将工具条(Toolbars)和Items区分开来。 -祝你生日快乐 - 小师妹妹。 +2009-08-29 v2.0.8 -ExtAspNet支持多语言(en,zh_CN,zh_TW),可以在Web.config修改。 -将所有的示例转化为英语版本。 -修正Tree控件的一个BUG(定义Mappings属性时)。 +PageManager.Instance应该存在于HttpContext.Current,而不是一个全局变量。 -这个BUG导致Asp.net compatibility的示例无法完成,现在已经修正。 +去除PageManager方法AddAjaxAspnetControls,增加属性AjaxAspnetControls。 -这个属性和Button得ValidateForms属性类似,可以查看Asp.net compatibility的示例。 +2009-08-25 v2.0.7 -为按钮增加DisableControlBeforePostBack属性 - 回发之前是否禁用按钮,防止重复提交 - 默认为true。 -Grid的Values属性访问限制由internal改为public,这就意味这可以自由改变Grid每个单元格的值了。 -增加示例-如何将Grid控件导出为Excel(data\grid_excel_run.aspx)(feedback:503684912)。 -如果TreeNode的属性Enabled="false",则此项变灰并且不会被选(feedback:your568)。 -修正TreeNode的属性NavigateUrl不接受服务器端URL(以~/开头)的BUG。 -增加Accordion和Tree配合使用的示例(other\accordion_tree_run.aspx)。 -修正Panel图标不能显示的BUG(CSSclass名不能有$字符)。 +去除PageLayout控件,此控件可以使用BorderLayout和指定PageManager的AutoSizePanelID属性来代替。 -这样所有需要占据全屏的Panel(不管你是Accordion,Panel,ContentPanel,Form,GroupPanel,SimpleForm,Tree还是Grid,TabStrip)都可以通过这种方式全屏。 -简单方便,示例可以参考 default.aspx 或者 other\accordion_tree_run.aspx。 +2009-08-14 v2.0.6 -动态生成菜单实例(other\menu_dynamic_run.aspx和other\menu_dynamic2_run.aspx)(feedback:shguo)。 -优化AJAX的内部实现,每个页面保存的ViewState现在减少1/3左右(重要更新)。 -优化Tree节点的NodeId自动生成,减少ViewState占用。 +2009-08-09 v2.0 beta5 +ExtAspNet和Asp.net的提交按钮兼容问题(feedback:千帆)。 -在2009-03-03 v1.3.0曾经提到这个兼容问题,并有这样的规则,如果Asp.net的按钮AJAX提交,必须设置UseSubmitBehavior="false" --也就是说生成的input的type不能是"submit",而这个限制在有些情况下是不可原谅的。 --我们做了优化,现在要使一个Asp.net的按钮能够AJAX提交,你不需要做任何设置(PageManager的属性EnableAjax为true即可,这是默认属性)。 +PageManager的实例方法AddAjaxUpdateControl改名为AddAjaxAspnetControls,现在可以在Page_Load设置需要在AJAX需要更新的Asp.net控件了。 -在Page_Load设置了哪些需要在AJAX更新的Asp.net控件会在回发时保持状态,可以通过RemoveAjaxAspnetControls来去除不需要更新的控件。 -示例在aspnet\fckeditor_run.aspx和aspnet\aspnet_run.aspx。 -FCKEditor和上传控件兼容。示例在aspnet\fileupload_run.aspx。 -修正ToolbarText的文本在AJAX下更新的BUG。 -Button的Pressed属性在AJAX可更新(feedback:mgzhenhong)。 -更新所有示例。在IE7.0,IE8.0,Firefox3.5,Chrome2.0下测试通过。 +2009-08-02 v2.0 beta4 +和Asp.Net的Forms Authentication兼容[feedback:mgzhenhong]。 -采用和Asp.Net Ajax类似的处理方式,需要在配置文件Web.config增加一个httpModules。 -现在支持Response.Redirect,你可以选择Response.Redirect或者ExtAspNet.PageContext.Redirect重定向页面,两者效果一样。 -支持FormsAuthentication.RedirectFromLoginPage(accountID, false);这样的方法。 -Button增加Type属性(button,reset,submit)[feedback:mgzhenhong]。 -修正Alert.Show方法不能指定文本前图片的BUG[feedback:xmq&mgzhenhong]。 -修正IE下某些弹出窗口的IFrame第一次不能加载的BUG。 -增加Menu和Accordion的示例。 -修正Window控件的IconUrl有时不显示(Target="_parent")的BUG[feedback:xmq&mgzhenhong]。 +2009-07-22 v2.0 beta3 -兼容FCKEditor。 -在IE8.0,Firefox3.5下测试通过。以后ExtAspNet将不会对IE6.0提供支持。 +2009-07-13 v2.0 beta2 -集成extjs最新版本v3.0。 +兼容IE6.0-7.0-8.0。 -这应该是Extjs3.0的一个BUG,在IE6.0-7.0下面设置Ext.QuickTips.init();会导致button的click事件无法响应(IE8下无此问题)。 -目前先禁用IE6.0-7.0的QuickTips。 -优化底层JavaScript。 +2009-07-05 v2.0 beta1 -更新extjs库到最新版本v3.0 RC2; 目前只有一个缺省皮肤(Theme)。 -使用YUI Compressor压缩JavaScript和CSS文件。 -Release版本每个页面只包含一个JavaScript文件(语言文件除外)和一个CSS文件。 -ExtAspNet自身的CSS会紧挨着页面标签引入,这样在<head><em>中</em>自定义的样式可以覆盖ExtAspNet缺省样式。 +Alert对话框会遮挡所有的Window窗口。 -使用一个变通的方法解决,因为无法改变Ext.Message的默认z-index(9000)所以将box.window_default_group的zseed调整为6000。 -为所有按钮的左右增加5px的空白边距:.x-btn button { margin: 0 5px !important; }。 -因为下拉列表不可编辑,所以不能为空,如果不设置SelectedIndex或SelectedValue,则默认选<em>中</em>第一项。 -重新绑定模拟树的下拉列表后,选<em>中</em>项的前面有图片的HTML标签的BUG。 -更新自定义JavaScript组件Ext.ux.SimplePagingToolbar。 -更新示例工程。 +2009-03-25 v1.3.1 -Tree在AJAX回发展开节点时JS错误[feedback:xlli]。[fixed] -Window<em>中</em>的EnableIFrame==false,则点击关闭按钮时报JS错误。[fixed] -页面包含FileUpload控件,需要点击按钮回发并上传文件,则不能采用原生AJAX方式。(参见示例aspnet/fileupload.aspx)[fixed] -HtmlEditor<em>显示</em>隐藏工具栏按钮不起作用,HtmlEditor目前不支持Enabled和Readonly两个属性。[fixed] +2009-03-03 v1.3.0 -如果弹出的窗口(Ext-Window)含有ASP.NET控件FileUpload,则此弹出窗口在关闭时出现JS错误(http://extjs.com/forum/showthread.php?t=8129)[feedback:xlli]。[fixed] -如果页面<em>中</em>存在ASP.NET控件(TextBox),则第二次提交表单就会报错(视图状态不对,其实时没有更新EventValidation隐藏字段导致的问题)。[fixed] -页面上放置ExtAspNet-Button和ASP.NET-Button,则点击ExtAspNet-Button时激发的是ASP.NET-Button的事件,这个BUG和Extjs2.2.1<em>中</em>Ext.Ajax.serializeForm的实现有关。[fixed] -ExtAspNet内部包含HtmlAgilityPack和Nii.JSON两个开源的第三方类库。[added] +如果以前你听过不要在ExtAspNet工程<em>中</em>使用ASP.NET标准控件的忠告,那么从v1.3.0版本开始,你可以忘掉这个说法,现在ExtAspNet控件和ASP.NET标准控件和平共处了。[fixed] -如果一个ASP.NET按钮控件要使用ExtAspNet的原生AJAX,只需要设置属性 UseSubmitBehavior="false" 即可。 -如果要在一次ExtAspNet的原生AJAX回发时更新ASP.NET控件的值,只需要调用PageManager的公共方法AddAjaxUpdateControl即可(示例:aspnet/aspnet.aspx)。 +2009-02-27 v1.2 beta9 -网络连接出错时的“Ajax Error”改成更加友好的提示信息“本次连接失败!可能是网络连接出错,请刷新页面重试。”。[fixed] -自动测试功能会在以后版本<em>中</em>逐步完善。这个版本完成测试框架,采用Extjs<em>中</em>JS函数进行大部分的测试,对于一些难以测试的地方借助jQuery完成。[fixed] +系统底层代码优化(主要是Javascript的封装和BUG修复)。[fixed] -底层使用Javascript创建一个Window控件的代码由原来的2000字符减少为500个字符。 -PageContext静态类<em>中</em>的GetPageStateChangedFunction改名为GetConfirmFormModifiedReference,底层代码优化。表示“获取当前页面<em>中</em>表单修改的确认提示框的脚本”。 ---[updated]删除PageContext<em>中</em>的GetConfirmFormModifiedReference,使用CurrentActiveWindow<em>中</em>的GetConfirmFormModifiedCloseReference/GetConfirmFormModifiedCloseRefreshReference/GetConfirmFormModifiedClosePostBackReference三个方法代替。 -不会修改弹出页面的URL(Ext-Window<em>中</em>的IFrame),以前为了实现功能为每个弹出页面添加box_parent_client_id查询字符串 -去除PageManager的RegisterPageStateChangedScript属性,现在已经将这个功能实现为静态的JS方法。可以通过PageContext.GetFormModifiedConfirmReference获取此方法的客户端脚本。 ---注意:以前的项目需要在所有的ASPX页面<em>中</em>查找RegisterPageStateChangedScript属性,并删除,否则会运行错误! -A页面有Ext-Window控件弹出B页面,B页面有Ext-Window控件弹出C页面,B页面的Ext-Window控件设置Target='_parent',则弹出的Ext-Window(C页面)会覆盖整个A页面,这是正确的。 ---当时如果用户直接访问B页面,就会报JS错误,因为此时找不到B页面的父页面A了。现在的版本修正为如果找不到父页面,则就在当前页面弹出窗口,这样用户直接访问B页面也不会出错了。 -Window控件的GetIFramePageStateChangedFunction函数改名为GetConfirmFormModifiedCloseReference,表示“获取先确认IFrame的页面<em>中</em>表单改变,然后关闭弹出窗口的客户端脚本”。 ---为Window控件增加如下两个方法GetConfirmFormModifiedCloseRefreshReference和GetConfirmFormModifiedClosePostBackReference,表示“先确认表单改变,然后关闭弹出Ext-Window,再然后刷新父页面或回发父页面”。 ---Window控件的OnClientCloseButtonClick属性如果不设置,则默认采用GetConfirmFormModifiedCloseReference,也即是先判断表单是否更新,然后在关闭窗口。 ---现在可以很方便的为Window控件的关闭按钮添加关闭后刷新父页面或者关闭后回发父页面的行为。 -如果弹出窗口(Window控件)<em>中</em>IFrame的页面不能正常加载(网络暂时出错或页面抛出异常),则此时点击右上角的关闭按钮会报JS错误,因为此时页面尚未加载完毕。 ---此版本修正了这个BUG,即时页面不能加载完全,也能通过右上角的关闭按钮关闭弹出含IFrame的窗体。 -Window控件的IFrameName属性是自动生成的,只读属性。(因为有可能所有的Ext-Window最终都渲染到最外层的页面,为了保证这些IFrame的name不同,IFrameName使用的是GUID,内部处理)。 -CurrentActiveWindow改名为ActiveWindow。 -[特别注意]GetWriteBackValueReference(string controlClientIds, string value, params string[] values)函数现在的定义是GetWriteBackValueReference(params string[] values) ---所有调用GetWriteBackValueReference的地方,需要删除第一个参数(一般是ActiveWindow.GetLoadStateReference())。 +2009-02-23 v1.2 beta8 -ContentPanel<em>中</em>内容不能自动扩展高度的BUG[feedback:huihuang]。[fixed] -DropDownList在Ajax回发时不能计算模拟树的<em>数据</em>[feedback:huihuang]。[fixed] -DropDownList在页面第一次加载时没有不可选择项,则回发时也不会有不可选择项的BUG。[fixed] -升级底层ExtJS类库为v2.2.1(此版本主要是Chrome的支持和部分内存泄漏问题的修正)。[fixed] -页面加载过程<em>中</em>的时间信息保存在Javascript变量window.box.timeInfo<em>中</em>。[added] +增加部分自动测试支持(使用WatiN和NUnit),下个版本将会提供完整的自动测试支持。[fixed] +2008-10-28 v1.2 beta7 -DropDownList没有选<em>中</em>任何一项,回发时报错[feedback:huihuang]。[fixed] -Window<em>显示</em>位置不对,以及不能拖动的BUG[feedback:huihuang]。[fixed] +PageContext优化。[fixed] -去除RegisterExclusiveScript静态函数(这是没有原生ajax之前的产物),使用RegisterStartupScript替代。 -去除RegisterStartupScript的重载函数,只保留最简单的PageContext.RegisterStartupScript(string script)函数。 -Resirect增加重载函数Redirect(string url, string target),其<em>中</em>target可能的取值为_self,_parent,_top,分别表示在当前窗口,父窗口,顶级窗口重定向[feedback:jqpeng]。 -Image控件增加ImageWidth/ImageHeight/ImageCssStyle/ImageCssClass/ImageAlt属性[feedback:jqpeng]。[fixed] -发布包<em>中</em>增加一个<em>Web</em>.config.txt,这是一个空的<em>Web</em>.config文件,包含BOX基本的配置信息。[fixed] -ContentPanel的ShowHeader和ShowBorder属性默认也是true(注意更新以前的应用)。[fixed] -Row和Column布局时,修正IE下设置RowHeight="100%"时<em>显示</em>不正确的BUG。[fixed] -AccordionLink当鼠标移上和移开时,有背景色的变化效果[feedback:huihuang]。[fixed] +TabStrip的Tab控件的EnablePostBack属性会在回发时保持(也即是说如果EnablePostBack=true,回发时没改变EnablePostBack的值,则每次切换到此Tab都会回发)。[fixed] -有这样一个效果,如果Tab1默认<em>显示</em>,Tab1的EnablePostBack=true,则页面加载完毕后会回发Tab1一次。 +2008-10-20 v1.2 beta6 +使用控件的站点必须建立虚拟目录,否则会报JS错误(即是脚本资源没有加载),却原来是HTTPCompress组件的问题。[fixed] -需要替换新的blowery.<em>Web</em>.HttpCompress.dll,解决方案见http://pohee.com/it/http-compression-in-aspnet-20/。 +DropDownList优化。[fixed] -去除EnableFirstItem/FirstItemText/FirstItemValue,这个并不能带来很大的好处,反而容易让开发人员困惑。 现在可以方便的在后台DropDownList1.Items.Insert(0, new ExtAspNet.ListItem("全部", "-1"));来达到同样的效果。 +如果某项(ListItem)的Value为空字符串,则通过SelectedIndex和SelectedValue不能选<em>中</em>[feedback:jqpeng]。 -和Asp.net<em>中</em>的保持一致,ListItem的Value值可以为空字符串。 也就是可以这样写DropDownList1.SelectedValue = ""; -ListItemCollection增加重载函数Add(string text, string value),这样方便后台添加列表项。 -处于布局内的容器控件(Layout!=LayoutType.Container),AutoHeight会自动设置为false(避免开发人员发生此类错误)。[fixed] -注意,控件的高度指的是整个控件的高度,包含BodyPadding(这和CSS<em>中</em>的height不同,CSS<em>中</em>的height是指内容的高度,除去padding/border-width/margin)。[fixed] +为所有控件属性增加在VS<em>中</em>的智能提示。[fixed] -需要将ExtAspNet.XML和ExtAspNet.dll放在一起,这样引用dll时xml会被拷贝到bin目录下,提供VS的智能提示。 +控件的属性如果是枚举类型,如果此属性可以不取值,则默认为None。[fixed] -TriggerIconType.Default -> TriggerIconType.None -SystemIconType.Empty -> SystemIconType.None -RegexPattern.USER_DEFINED -> RegexPattern.None -表单验证属性名称变化(ValueToCompare->CompareValue,ControlToCompare->CompareControl)。[fixed] +注意:一个属性可以拥有多个值的情况。[fixed] -属性和CSS相关则用空格分隔(比如ColumnWidths,BodyPadding)。 -其他的都是逗号分隔(比如ValidateForms,DataKeyNames,DataNavigateUrlFields)。 +AccordionLink实现为控件。[fixed] -可以方便的在子页面(iframe)<em>中</em>通过js切换父页面<em>中</em>选<em>中</em>的菜单项(Accordion->AccordionLink)(示例在other/accordion_links_run.aspx,other/accordion_links_run_iframe_htm)[feedback:jima]。 +确认:可以方便的动态添加控件,并且可以给控件添加服务器端事件(示例在form/form_dynamic_run.aspx)。[fixed] +2008-10-15 v1.2 beta5 -验证表单字段的ValueToCompare属性,为字符串时会出错的BUG。[fixed] +优化下拉列表。[fixed] -验证下拉列表时,应该取ListItem的Value属性进行验证,而不是Text属性。 -DropDownList的Items增加Insert方法(可方便的下拉列表选项添加“全部”)。 -DropDownList不支持EmptyText属性。 -ListItem启用EnableSelect和SimulateTreeLevel属性,这样就可以直接在前台(ASPX)<em>中</em>设置哪些项不可选择,以及创建模拟下拉树。 -DropDownList增加EnableSimulateTree属性(默认为false),如果设置了DataSimulateTreeLevelField,则自动将EnableSimulateTree设置为true。 +2008-09-27 v1.2 beta4 +EnableLargeHeader属性对所有容器的效果一样,Accordion的属性EnableLargeHeader只会改变Accordion的标题大小,而不会对AccordionPanel起作用(示例见other/accordion_run.aspx)。[fixed] -Accordion去除EnableHightlight属性,AccordionPanel增加EnableHightlight属性。 -影响以前使用Box的应用,需要将Accordion的属性去掉,然后为每个AccordionPanel增加EnableLargeHeader和EnableHightlight属性。 -AccordionPanel鼠标移上去的样式调整(现在没有下面的一条白线了)。[fixed] +AccordionPanel增加Links属性,可以绑定列表<em>数据</em>到AccordionPanel,呈现的是链接的列表(示例在other/accordion_links_run.aspx)。[fixed] -原来放置在AccordionPanel<em>中</em>的容器,比如ContentPanel需要在外层加上<Items>标签。 -适当增大AccordionPanel<em>中</em>链接的高度20px->22px,同时对链接的样式也做了微调。 -通过BodyPadding控制链接列表的边距。 -这样能大大减少ASPX<em>中</em>HTML代码和Javascript代码的书写,可以在后台动态添加链接,效果很赞,此需求由马季提出。 +2008-09-25 v1.2 beta3 +代码优化与设计时支持(尚需要不断完善,目前可以在ASPX页切换到“设计时”,方便属性的更改和事件处理函数的添加)。[fixed] -Panel/GroupPanel/ContentPanel/Tree/HiddenField/PageLoading -TabStrip/Toolbar -TabStrip去除Plain属性,增加EnableTitleBackgroundColor(默认为true)。[fixed] -向Form<em>中</em>动态添加控件的BUG,现在form/form_dynamic_run.aspx示例已经能正确运行。[fixed] +大部分容器的子控件集合更正为Items(以前有些是Rows)。[fixed] -影响的控件包括Toolbar/Accordion/AccordionPanel/GroupPanel/Panel/SimpleForm/Window等。 -保留Form的Rows(FormRowCollection)属性和Grid的Rows属性(GridRowCollection)。 -保留TabStrip的Tabs(TabCollection)属性。 -保留PageLayout/BorderLayout的Regions(RegionCollection)属性。 -预祝今晚神七发射成功。 +2008-09-22 v1.2 beta2 +Grid选<em>中</em>项(SelectedRowIndexArray)在ajax回发过程<em>中</em>存在BUG [feedback:xmzhu]。[fixed] -表现为对Grid进行多次删除添加操作后,SelectedRowIndexArray选<em>中</em>项<em>中</em>会存在当前不存在的行序号,导致服务器端遍历选<em>中</em>项时数组越界。所有使用box控件的应用程序都受到此BUG的影响,需尽快更新到新版本。 +代码优化与设计时支持(示例<em>中</em>表单控件都已支持设计)。[fixed] -PageManager/SimpleForm/Button/HyperLink/Label/Image/LinkButton/TextBox -TriggerBox/TwinTriggerBox/Window/TextArea/HtmlEditor/DatePicker/NumberBox -CheckBox/RadioButton/RadioButtonList/DropDownList -Grid +2008-09-19 v1.2 beta1 -Image/LinkButton/HyperLink增加一些Ajax可更新属性。[fixed] +隐藏的方式由HideMode属性控制Visibility/Offsets/Display。[fixed] -修正Form/SimpleForm<em>中</em>隐藏一个表单字段(Hidden=false)会占据页面空间的BUG。 -ToolbarText/ToolbarFill/ToolbarSeparator在ASPX<em>中</em>设置Hidden=true不起作用的BUG [feedback:jbzhang]。[fixed] -Button去除MarginRight属性(可以通过CssStyle="margin-right:5px;"达到相同的效果)[fixed] +2008-09-09 v1.1 +Toolbar去除IsPageMenu属性,在网报<em>中</em>可以用自定义样式实现,而不应该写在控件<em>中</em>。[fixed] -网报:CssClass="toolbar-pagemenu" CssStyle="border:0px;",同时定义样式:.toolbar-pagemenu{ background: rgb(208, 222, 240) url(../images/pagemenu_toolbar_background.gif) repeat-x left top;}。 -Region去除默认的Layout=Fit,如果希望Region使用Fit/Anchor/Column/Row等布局的话,需要手工指定。[fixed] -ToolbarSeparator/ToolbarFill在Ajax更新Hidden属性的BUG。[fixed] +布局整理。[fixed] -新增Column/Absolute/Row三种布局,加上以前的Container/Fit/Anchor/Accordion/Border/Form六种布局,总共有9<em>中</em>布局可供使用。 -其<em>中</em>一些控件默认使用一种布局:SimpleForm(Form)/Form(Form)/Panel-GroupPanel(Container)/Accordion(Accordion)/PageLayout(Border)/BorderLayout(Border)/TabStrip(Card),所有布局控件默认的布局是Container。 -经常用到的布局控件:SimpleForm/Form/Accordion/TabStrip/BorderLayout,经常用到的布局:Fit/Row/Anchor +2008-09-08 v1.1 beta7 -MenuButton/MenuHyperLink增加HideOnClick属性,如果一个菜单项的作用仅仅为了弹出下级菜单,点击没反应,则可以这样设置HideOnClick="false" CssStyle="cursor:default;" [feedback:huayu]。[fixed] -MenuButton/MenuHyperLink/MenuSeparator/MenuText增加Hidden属性(此属性是Ajax可更新属性,如果需要在Ajax时<em>显示</em>隐藏菜单,请使用此属性而不是Visible属性)。[fixed] +大部分的ExtAspNet控件增加Hidden属性(少数几个控件没有此属性:Menu),这样在Ajax时可以<em>显示</em>隐藏控件。[fixed] -注意Visible和Hidden的区别:Visible=false的属性不会渲染到客户端,Hidden=true的控件渲染到客户端但是隐藏。 -US的ExtAspNet改造强烈依赖于此属性,这个版本发布后可以继续。 -网报<em>中</em>唯一没有用到ExtAspNetAjax的地方就是<em>显示</em>隐藏表单字段,现在也可以使用Ajax了。 +2008-09-04 v1.1 beta6 -PageContext.Redirect支持普通页面转向和ExtAspNetAjax下页面转向。[fixed] +模拟树的下拉列表的BUG(会使一些可选项变成不可选项)[feedback:xmzhu]。[fixed] -因为if("0,2,9,11,".indexOf('1,')>=0){ok},这显然是不对的,此BUG涉及很多控件(Grid,DropDownList,TabStrip)。 -解决方法:testValue += '';if(domValue.split(',').indexOf(testValue) >= 0){ok}。 -DropDownList在Ajax时应该先更新<em>数据</em>再设置选定项 [feedback:xmzhu]。[fixed] -Button/MenuButton增加Ajax可更新属性OnClientClick [feedback:xmzhu]。[fixed] -Tree的Ajax支持(尚需优化)。[fixed] +2008-09-02 v1.1 beta5 -DropDownList如果第一次没有绑定值,应该绑定到[[]](二维数组),而不是[](一维数组)。[fixed] -模拟树的DropDownList,在Ajax重新绑定DataSource后,保持项是否可选状态是最新的(页面第一次加载时,即使没有<em>数据</em>也需要设置DataTextField/DataValueField/DataSimulateTreeLevelField/DataEnableSelectField等属性的值,否则Ajax回发时会出错)。[fixed] -UserControlConnector导致的Ajax错误,去除UpdatePanelConnector控件(以后不会用AspnetAjax,这个控件已经完成使命)。[fixed] -不要使用Asp.net的控件HiddenField,而是使用ExtAspNet的HiddenField,因为Asp.net的控件在Ajax不会被更新,所以会导致视图状态不一致的错误。[fixed] -网报Ajax整合基本完成(除了待审批->下一步[审核/归档/出纳]操作,由于需要<em>显示</em>隐藏表单字段,目前Ajax不支持,使用的还是普通的PostBack)。[fixed] -IE下,RadioButtonList<em>中</em>项如果存在汉字,则会换行的BUG。[fixed] -增加两个Theme[Slate/Black](样式尚需完善)。[fixed] +2008-09-01 v1.1 beta4 -非当前Tab<em>中</em>如果有ContentPanel,则在页面上方会有空白(可以通过设置EnableDeferredRender=false解决,但会减慢页面的加载速度),现在已经解决这个问题。[fixed] -RadioButtonList去除EnableBackgroundColor/EnableLightBackgroundColor属性,背景色是透明的,也就是和父控件(SimpleForm/Form)的背景色一致。[fixed] -TwinTriggerBox的第一个Trigger图标不会先<em>显示</em>再隐藏,而是直接隐藏掉(如果用户设置ShowTrigger1=false)。[fixed] -<em>Web</em>.config<em>中</em>增加配置项FormLabelWidth="80"(默认为80),同时PageManager增加FormLabelWidth属性用来控制页面上所有SimpleForm/Form的表单字段标题的宽度。[fixed] +完善Ajax。[fixed] -RadioButtonList增加Ajax可更新属性SelectedIndex(SelectedValue/SelectedItem)。 -DropDownList增加Ajax可更新属性Enable/SelectedIndex(SelectedValue/SelectedItem)/DataSource。 -Grid增加Ajax可更新属性Columns(也就是说Grid列在回发时隐藏<em>显示</em>了一些,也能正确的Ajax)。 -ToolbarText增加Ajax可更新属性Text。 +2008-08-31 v1.1 beta3 -TabStrip增加EnableDeferredRender属性(是否启用延迟加载Tab,默认启用)。[fixed] -重定向页面,使用系统的方法 PageContext.Redirect(string url),使用Response.Redirect方法会出错。[fixed] +安全的Ajax设计。[fixed] -这个版本Ajax和上个版本(v1.1beta1)在设计思路上有很大区别,同时在速度上会有进一步的提升。 -基本思想:安全的Ajax交互,明确Ajax回发时支持控件哪些属性的改变,这将适合90%的应用场景(并且具有极快的反应速度),对于需要UI大改动的可采用常规回发,系统提供控件级别的EnableAjax属性。 -整理支持Ajax的控件属性改变列表(所有被支持的属性改变都是安全的、快速的,所有不被支持的属性改变不会对UI起作用,同时是安全的,不会有js错误)。 -网报Ajax整合(目前只支持所有的列表页面)(v0.8.1)。[fixed] +2008-08-29 v1.1 beta1 +Window控件是否弹出的状态在回发时维持。[fixed] -控件设计的一个原则,凡是可以在客户端改变的属性都应该在回发时保持属性的状态。 +完全抛弃Asp.NetAjax,ExtAspNet控件内置Ajax支持。[fixed] -这是一个值得骄傲的设计,可以明显提高页面回发的速度(相比普通的回发和Asp.netAjax的回发),对于IFrame框架的交互也起到很好的加速效果。 -不需要做任何配置,所有的回发都是Ajax(在<em>Web</em>.config和PageManager<em>中</em>有设置启用Ajax回发的属性-EnableAjax-默认为true)。 +在这种设计下,其实可以完全抛弃Javascript。 -比如简单的点击一个按钮弹出窗口,可以在Button的OnClick事件<em>中</em>设置Window1.Popup=true,也可以注册Button的OnClientClick=Window1.GetShowReference()。 -第一种方法需要回发,但是我们内置的Ajax支持能很快的返回需要的结果并解析,在网络速度很快的情况下和第二种方法差别不是很大。 -推荐的做法是尽量用客户端实现,客户端实现复杂的直接用服务器端实现。 +目前ExtAspNetAjax的限制。 -只对ExtAspNet控件起作用,对Asp.net控件不起作用。 -对容器控件(有子控件的控件)不起作用,只对最底层的控件起作用。 -对改变控件的Visible属性会有错误。 -Window控件的属性改变只有少数几个起作用(Popup,IFrameUrl)。 -PageManager增加属性EnablePageLoading和EnableAjaxLoading(启用页面第一次加载标示和Ajax加载标示,默认都为true),所以如果使用系统默认的加载标示就不必每个页面都添加PageLoading控件。[fixed] -Grid<em>中</em>的回发事件(主要是LinkButtonField和CheckBoxField(RenderAsStaticField=false))要延迟0ms执行,这样当前行被选<em>中</em>的状态在回发后会得到保持。[fixed] -Grid选<em>中</em>行的状态在第一次回发时不能保持的BUG。[fixed] +2008-08-26 v1.0 +已知问题:IE的ActiveX插件IE Developer Toolbar会对IFrame的加载造成0.5m左右的延迟。 -主要是父页面加载一个比较大的css文件(~100k),则每次打开iframe页面,onload事件的调用都会有500ms左右的延迟,在测试IE性能时要禁用此插件。 +优化弹出窗口<em>中</em>IFrame的<em>显示</em>速度。[fixed] -在当前页面弹出窗口需要~20ms,在父页面弹出窗口需要100~300ms。通过缓存弹出的窗口实例,从而第二次弹出窗口不再需要创建时间。 -PageLayout的Region增加SplitColor属性,默认的背景色是透明的。(在网报<em>中</em>需要设置SplitColor="#CADDF7",以便分隔符的颜色和Toolbar的颜色一致)[fixed] +PageManager增加属性Theme、Language、FormMessageTarget、FormOffsetRight等属性,这些属性可以在<em>Web</em>.config<em>中</em>设置(推荐方法),也可以为每个页面设置。[fixed] -一个典型的应用是为每个用户设置不同的皮肤(根据用户浏览器<em>中</em>Cookie设置的值)(示例在default.aspx)。 -TreeNode增加属性SingleClickExpand,表示点击可切换节点的折叠展开状态。[fixed] +TabStrip<em>中</em>非当前Tab会延迟渲染。[fixed] -这会明显加快页面的渲染速度,网报<em>中</em>一个典型的费用审批页面可以减少200ms的渲染时间。 -由于非当前Tab不会在页面加载时渲染,所以那些Tab<em>中</em>的节点在页面加载后也是不可见的,需要将相关的脚本移动到控件的render事件<em>中</em>。 -不能比较两个DataPicker大小的BUG。[fixed] -TabStrip延迟加载引起的BUG(非当前Tab<em>中</em>的ContentPanel会占据页面空间,已修正)。[fixed] -全新的ExtAspNet.Examples(基础知识/表单控件/<em>数据</em>绑定/容器布局/IFrame框架)。[fixed] +2008-08-19 v0.4 beta6 +PageManager增加两个属性(EnableInlineStyleJavascript/ApplyParentStyleJavascript),可以在IFrame页面<em>中</em>使用父页面的脚本和样式(示例在iframe/default.aspx和iframe/page3.aspx)。[fixed] -测试发现,IFrame页面的加载速度并没有明显加快,可以先不使用此属性。 -RadioButtonList放在在BorderLayout<em>中</em><em>显示</em>不了的BUG [feedback:zgjiang2]。[fixed] +extjs的BUG,当页面<em>中</em>含有iframe时,Ext.onReady会被调用两次(IE6/IE7)(http://www.extjs.net/forum/showthread.php?t=43246)(示例在test.aspx)[fixed] -现在的解决方法是在初始化时:if(this.initialized){return;}this.initialized=true; +需要先回发页面再弹出IFrame窗口。[fixed] -在回发时设置窗口的Popup和IFrameUrl属性,因为这些属性是可以保持状态的,所以在关闭窗口时要注意设置Popup=false。 -另一种做法(推荐):PageContext.RegisterStartupScript(Window99.GetShowReference("./simpleform.aspx"));。 +2008-08-15 v0.4 beta5 -点击关闭窗口的按钮,在IE6下会有JS错误。[fixed] -增加BorderLayout控件,示例在iframe/borderlayout.aspx。[fixed] +Radiobuttonlist<em>显示</em>有重影(示例在radio.aspx)。[fixed] -全新的样式。 -去除Horizontal属性,增加ColumnNumber(可以设置渲染成几列)。 -GetValueReference取得的值不正确的BUG。 -动态向Form<em>中</em>添加FormRow,并动态的向FormRow<em>中</em>添加表单字段,以及如何取得表单字段的值。(示例在form_dynamic.aspx)[fixed] +IFrame弹出窗口关闭后回发父页面,则会多加载IFrame一次,再次打开窗口会重复加载IFrame2-3次[feedback:xmzhu]。[fixed] -这是一个重要的BUG,会严重影响页面的加载速度。原因是通过脚本改变的IFrameUrl会在回发时保持状态,从而回发父页面后Window<em>中</em>的IFrame被添加到页面,而这是不需要的。 -现在"是否弹出窗口、窗口标题、IFrameUrl"在客户端的改变,不会影响服务器端的属性,也即是不保持状态。此问题解决。(示例在button_iframe.aspx) +2008-08-13 v0.4 beta4 -点击关闭窗口的按钮,在IE下会有JS错误。[fixed] -Window的右上角关闭图标增加提示,优化事件响应。[fixed] -Window的代码重构。[fixed] +修正一个的内存泄漏。[fixed] -IE7下测试,打开iframe/default.aspx页面,iexplorer占内存68.368M。 -内存存在泄漏时,点击iframe/page3.aspx页面8次后iexplorer占118.792M内存。 -修正后,点击iframe/page3.aspx页面8次后iexplorer占76.492M内存。 -IE窗口最小化时,IE会自动进行垃圾回收。 +2008-08-12 v0.4 beta3 -底层的javascript框架Extjs升级为v2.2,Grid的渲染速度有很大提升。[fixed] -Grid的EnableDelayRender默认为true(如果没有设置Grid的高度或通过布局间接设置高度,则行不可见,可以通过AutoHeight="true"解决)。[fixed] +页面正在加载的提示尽早的<em>显示</em>出来。[fixed] -首先在执行js来完成页面渲染之前延迟5ms,以便浏览器把当前页面内容<em>显示</em>出来。 -加载js脚本的script标签放置在页面的最后,放置加载js而阻塞PageLoading的<em>显示</em>。 +2008-08-08 v0.4 beta2 -TabStrip延时加载出错。[fixed] -Window的IFrameUrl处理的BUG,比如Pages_ExtAspNet目录下的页面应该为./FE_ApplyEditor.aspx或~/Pages_ExtAspNet/FE_ApplyEditor.aspx。[fixed] -Window的WindowPosition="Center"并且Target="_parent",则会JS错误。[fixed] -实现网报首页下拉菜单和左侧菜单的导航功能。[fixed] -Window的创建在页面<em>显示</em>后进行,不计算在js渲染时间内。[fixed] -优化费用申请页面(尽量减少不必要的层次嵌套)。[fixed] -button_iframe.aspx默认会加载form.aspx页面(Window控件的BUG)。[fixed] -Window<em>中</em>的保存并关闭按钮和Asp.netAjax冲突。[fixed] -优化关闭Window的js脚本,减少写到页面的js大小。[fixed] -加快“保存并关闭”按钮关闭窗口的速度,使用PageContext.RegisterExclusiveScript(CurrentActiveWindow.GetClosePostBackReference());,示例在(simpleform.aspx)。[fixed] +2008-08-05 v0.4 beta1 -DropDownList去除Traditional属性,和传统的Asp.net控件一样不可编辑。[fixed] -DropDownList增加SelectedText属性(去除了模拟树时通过SelectedItem.Text的多余html字符)。[fixed] -为了加快渲染速度,去掉一些特效(比如Panel的折叠效果,Grid的拖动列效果等)[feedback:dcding]。[fixed] -将生成的js对象的名称简单化,这样可以减少生成的js内容,加快页面加载速度(一个典型页面的js由原来的33.0k降低为21.4k)。[fixed] +弹出窗口<em>中</em>,点击按钮回发然后点击关闭按钮,出现js错误 [feedback:xmzhu]。[fixed] -因为在页面的Page_Load<em>中</em>,if (!IsPostBack){PageContext.RegisterPageStateChangedStartupScript();}通过这样方法向页面注册了一段脚本,但是这段脚本在回发时没有注册到页面,因为js调用此脚本时报错。 -一种解决方法是将向页面注册脚本的函数移动到if语句的外面,即每次都向页面注册此脚本。 -另一种办法就是在PageManager控件<em>中</em>增加RegisterPageStateChangedScript(向页面注册监视页面<em>中</em>表单内容改变的脚本)的属性(会在每次页面回发(包含ajax回发)时注册脚本)(示例在button_iframe.aspx/simpleform.aspx)。 +PageManager控件增加ExecuteOnReadyWhenPostBack属性(示例在onreadyscript.aspx)。[fixed] -这个手工添加onReady函数能够在每次页面回发时都注册脚本(包括Ajax局部回发),这就避免了手工去做的麻烦(已经在网报<em>中</em>遇到这种情况)。 -每个页面必须添加一个PageManager控件,否则会出错,同时去除DesignTimeStyle控件(作为PageManager的属性出现)。[fixed] -TextField等表单字段增加Readonly属性。[fixed] +全新设计的IFrame的架构(尽可能和基于MasterPage的架构保持兼容,和Asp.net Ajax保持兼容)。[fixed] -最大的好处是可以减少页面下载完毕后Javascript渲染时间(可以节约一般的渲染时间)。(所有示例在iframe文件夹下) +示例1,通过点击按钮弹出IFrame窗口,可直接关闭父页面,也可在关闭后刷新或回发父页面。(default.aspx/page2.aspx/simpleform.aspx) -虽然IFrame和Master两种架构差异迥然,或许你以为需要修改一堆代码来完成这种转换,起初我也是这么认为的,但是现在你所要做的仅仅是为Window控件增加一个属性(Target="_parent"),就完成了两种框架的转换,是不是很酷。 -显然,控件本身封装了大量的代码,简单来看现在有三个页面(default.aspx(A)/page2.aspx(B)/simpleform.aspx(C)),其<em>中</em>A包含B页面,当你在B<em>中</em>打开包含有页面C的窗口时,窗口不是在B<em>中</em>打开,而是在A<em>中</em>打开,这样才能保证窗口覆盖整个页面,当你从C<em>中</em>返回需要回发页面B时,却发现取得的是A页面,因为我们窗口是在A页面<em>中</em>创建的。我会通过一篇文章来揭示这一过程,敬请期待。 -示例2,Grid<em>中</em>弹出窗口。(default.aspx/page3.aspx/simpleform.aspx) +示例3,TriggerBox弹出窗口。(default.aspx/triggerbox.aspx/simpleform.aspx) -在整个页面弹出窗口或者在当前页面弹出窗口,仅仅设置Window的Target属性即可。 -示例4,弹出窗口<em>中</em>的弹出窗口。 -对整个Examples更新测试。[fixed] +2008-07-31 v0.3 beta12 -IE下TabStrip在Ajax回发后不会去掉x-hide-display样式,导致Tab<em>显示</em>为空的BUG。[fixed] -对TabStrip/Panel/Window<em>中</em>的IFrame重新设计,如果设置IFrameUrl="#"或者"about:blank",则不渲染iframe到页面节点,同时第二次打开Window<em>中</em>的IFrame不会有残影出现。[fixed] -如果TabStrip的Tab不是激活Tab并且设置了IFrameUrl,则会延迟加载(示例在tabstrip_iframe.aspx)。[fixed] -Tree控件,点击一个节点自动回发,则当前点击的那个节点的选<em>中</em>状态不会保持的BUG [feedback:zgjiang2]。[fixed] +规范关闭窗口时提示用户保存已经修改的内容提示的调用方式(包含iframe<em>中</em>关闭按钮和window右上角关闭图标的调用方式)(示例在grid_iframe.aspx/simpleform.aspx)。[fixed] -内部实现上,点击“保存并关闭按钮”,可以将关闭窗口的脚本更早的执行(在simpleform.aspx,PageContext.RegisterStartupScript增加重载函数),而不是原来的先创建整个页面UI,再关闭窗口。 -参照Yslow的评分规则,将JS文件引用由head移动到body<em>中</em>。[fixed] -Firefox下,如果页面太长会出滚动条,原来在ViewPort样式<em>中</em>有body{overflow:hidden;}。[fixed] +IFrame内的页面宽度和高度会自动设置(是不是还在为1px/2px的白边而烦恼,现在不用了:-)(示例在iframe_autosize.aspx/simpleform.aspx/simpleform2.aspx)[fixed] -增加PageManager控件(需要指定AutoSizePanelID,即需要设置宽度和高度为整个页面的宽度和高度的Panel),HideScrollbar属性用于隐藏滚动条(IE/Firefox)。 +2008-07-24 v0.3 beta11 -<em>web</em>.config配置信息<em>中</em>MessageTarget改名为FormMessageTarget,增加FormOffsetRight配置项,用来定义全局表单字段距离右边界的宽度,同时每个表单字段都增加OffsetRight属性 [feedback:jima]。[fixed] -Window在回发时设置的Title不起作用的BUG。[fixed] -增加Image控件 [feedback:jima]。[fixed] -Tree控件,如果一个节点不是叶子节点并且没有子节点,则应把它的Expanded设置为false,否则会引起页面死循环回发 [feedback:zgjiang2]。[fixed] -Image增加ToolTipTitle/ToolTipAutoHide两个属性,当提示信息特别长时,可以让用户阅读完毕之后手工关闭提示信息(示例在hyperlink.aspx)。[fixed] -去掉DropDownList控件的Text属性(强制性),可以通过设置SelectedValue来设置选<em>中</em>哪一项 [feedback:xmzhu]。[fixed] -过滤提示消息<em>中</em>的换行符(转换为<br/>),否则提示信息可能导致页面渲染错误 [feedback:dcding]。[fixed] +2008-07-23 v0.3 beta10 +完善Tree控件。[fixed] -如何将<em>数据</em>库<em>中</em>的<em>数据</em>绑定到Tree(示例在tree2_bind_database.aspx)。 -ajax加载树节点,放在UpdatePanel<em>中</em>才有ajax的效果(示例在tree2_ajax.aspx)。 -更改TreeNode的ID为NodeId,否则两个树<em>中</em>不能有相同ID的TreeNode,这是不合理的。 -Grid的GridColumn的ID改名成ColumnId,否则同一个页面放置两个Grid,它们的GridColumn的ID不能同名,这是不合理的。注意需要更新以前的代码![fixed] -Grid所有类型的列增加DataTooltipField/DataTooltipFormatString两个字段,以<em>显示</em>ToolTip(示例在grid.aspx)。[fixed] +2008-07-22 v0.3 beta9 +IE6下,左侧导航链接的选<em>中</em>样式,以及鼠标移上去和移开的样式不对。[fixed] -发现原来ie6不能正确解析li的高度,必须手工设置才行(style="height:20px;")。 +IE6/IE7下,模拟树的下拉列表如果文字长度太长,则<em>显示</em>的文字会换行,导致错位。[fixed] -虽然最后未能解决<div style="width: 60px; white-space: nowrap; overflow: hidden; border: solid 1px red;"><div style="width: 16px; height: 18px; float: left;">##</div>差旅交通费</div>在IE和Firefox下<em>显示</em>的不同效果。 -但是通过用<img src="##" />来代替<div style="background:url(##)" />,从而实现FF和IE下样式的统一。 -刚看到old9的解决方案:把“差旅交通费”改成“<span style="margin-right: -1000px;">差旅交通费</span>”,在IE下和FF下的都不换行,:-) -LinkButton增加OnClick事件 [feedback:huihuang]。[fixed] -Window通过设置IFrameUrl和Popup不起作用的BUG。[feedback:xmzhu]。[fixed] +增加树控件(Tree)(示例在tree2.aspx)。[fixed] -可以在回发时维持树的状态(选<em>中</em>行,折叠/展开,CheckBox)。 -可以通过Inline的方式添加树节点,也可以绑定到XmlDocument/XmlDataSource/SiteMap。 -点击树节点可以链接到页面,也可以引发PostBack事件,可以添加自定义脚本。 +2008-07-16 v0.3 beta8 +ContentPanel<em>中</em>放置ExtAspNet控件,则渲染时会出现各种问题,比如下拉列表<em>显示</em>样式出错,Grid没了滚动条等等。[fixed] -隐蔽性非常强,原来在ContentPanel<em>中</em>渲染ExtAspNet控件,如果容器的display='none',则会出现各种问题(主要是大小不对)。 必须设置容器为visibility='hidden',然后在渲染完成后<em>显示</em>容器。 -现在Grid只要<em>显示</em>的设置高度和宽度,或者隐式的设定宽度高度(通过Anchor或Fit布局实现),只要超过Grid容器就会<em>显示</em>滚动条。 +IE6下,在应用Asp.NetAjax后,Form<em>中</em>字段的宽度渲染不正确。[fixed] -调试相当困难,如果你有过在IE下通过alert发现问题的经历,你就能明白。 -最后发现IE6下应用Asp.NetAjax后不仅Form<em>中</em>列的宽度设置不正确,而且主内容区域的宽度设置也不正确,不过最终我们还是顽强的修复了IE6下的这个BUG: 在MasterPage的onReady函数<em>中</em>,首先修正内容区域的宽度(region3.setWidth(pageLayout1.getSize().width - region2.getSize().width - 5);region3.doLayout();),然后修正页面<em>中</em>所有表单的宽度(box_fixFormWidthInIE6();): 示例在 Site.Master 页面。 +集成的AspNetAjax有一个很大的BUG,只要你在页面上进行过ajax操作,当改变窗口大小时你会惊讶的发现内容区域的内容全部为空了![fixed] -解决方法相当怪异,经过一个下午的不断尝试,终于用一个怪异的方法解决(box.{0}.setSize(box.{0}.getSize());box.{0}.doLayout();), 这样的代码让我想起刷新窗口时那个方法(window.location.href=window.location.href;),不管怎么说,我对能很好的解决这个重大的BUG很是欣喜。 +2008-07-14 v0.3 beta6 -增加FlashObject控件。[fixed] -PageLoading增加EnableFadeOut属性(默认false),可以启用淡出效果。[fixed] -Accordion选<em>中</em>样式微调。[fixed] -预加载Form表单出错时提示信息的背景图片。[fixed] +Grid增加EnableDelayRender属性(默认false),可以加快页面的渲染速度(一个典型的20个记录的页面,可提前0.7s-1s<em>显示</em>出来)。[fixed] -因为延迟加载<em>数据</em>不会改变Grid的大小,所以对于非布局内或不设定高度宽度的Grid,需要设置"EnableDelayRender=false"。 -改变Grid<em>中</em>静态的CheckBoxField图片。[fixed] -TabStrip增加TabIndexChanged事件,同时Tab增加EnablePostBack,可以在点击一个Tab时引起回发事件。这在延迟加载Tab的内容非常有用。(示例在tabstrip.aspx)[fixed] +2008-07-12 v0.3 beta5 -页面菜单Toolbar的分割符和背景不相融合。[fixed] -表单字段之间可以比较大小,比如NumberBox可以和Label比较大小,同时增加CompareType,来指定比较的类型(示例在form_compare.aspx)。[fixed] -如果是同种类型的表单字段,不需要指定CompareType,比如两个NumberBox比较值的大小不需要指定CompareType,而一个NumberBox和TextBox比较大小需要指定CompareType。 +如果在编辑页面使用AspNetAjax,则不能在回发时关闭当前窗口[feedback:huihuang](示例在ajax_editor_main.aspx/ajax_editor.aspx)。[fixed] -这是由于ajax后执行的javascript<em>中</em>不能有return false语句。 +在文本框失去焦点时,执行一些Javascript脚本(示例在textbox_blur.aspx) [feedback:xmzhu]。[fixed] -在页面添加onReady函数(会被系统调用),然后用javascript监视文本框值的改变。 -弹出Window默认<em>显示</em>的错误页面,解决方法在当前目录添加一个空的html页面,然后把Window控件的IFrameUrl指向这个页面而不是"#"。[fixed] +弹出的窗口<em>中</em>的弹出窗口的如果内容发生变化,则点击右上角的关闭按钮时会有提示用户先保存的对话框,但是这个对话框的被第二个弹出窗口覆盖了 [feedback:xmzhu]。[fixed] -原来的调用方法太麻烦(见示例<em>中</em>alert\alert_1.aspx和alert\alert_2.aspx,总计 6 行代码),现在只需要 3 行代码就OK了。 -点击提交按钮后变成灰色不可再次点击(示例在button_click_gray.aspx)[feedback:jima]。[fixed] +增加Menu、MenuText、MenuSeparator、MenuButton、MenuHyperLink控件,用于按钮的下拉菜单(示例在button_menu.aspx)。[fixed] -增加SplitButton控件。[fixed] +2008-07-09 v0.3 beta4 -DataPicker默认的日期格式为(yyyy-MM-dd)。[fixed] +Form表单字段(TextBox,DropDownList...)之间可以比较大小 [feedback:huihuang]。[fixed] -增加ControlToCompare/ValueToCompare/CompareOperator/CompareMessage四个属性,示例在form_compare.aspx。 +TabStrip<em>中</em>放置IFrame会出现渲染错误 (示例在tabstrip_iframe.aspx)[feedback:jima]。[fixed] -特殊处理,拥有IFrame的Tab如果不是激活Tab,则不设置Url,只有在激活时才设置Url。 -RadioButtonList增加AutoPostBack属性(示例在radio.aspx) [feedback:xmzhu]。[fixed] -FormRow可以设置各列的宽度百分比 (示例在form_columnwidths.aspx)[feedback:jima]。[fixed] +表单字段Enable=false时<em>显示</em>颜色太浅 [feedback:jima]。[fixed] -覆盖缺省样式的.x-item-disabled,设置不透明。 +2008-07-08 v0.3 beta3 -Grid没有<em>数据</em>,向后翻页按钮可以点击的BUG [feedback:huihuang]。[fixed] +增加HiddenField控件。[fixed] -其实用TextBox也能模拟HiddenField的行为,只需要设置CssStyle="display:none;"即可。 +TriggerBox 如果 EnableTextBox = true,则不能将Text回发(这是html的限制)。[fixed] -最后的解决方案居然是设置 readonly=true,同时更改属性为 Readonly(示例在textbox2.aspx)。 -模拟树的下拉列表在失去焦点后<em>显示</em>的文字不对的BUG。[fixed] +控制下拉列表某些项不可以选择(示例在dropdownlist2.aspx)。[fixed] -增加 DataEnableSelectField 属性,不可选择的项变灰,并且鼠标经过时没有样式。 -LinkButton和Grid的LinkButtonField增加Enable属性(示例在hyperlink.aspx和grid.aspx)。[fixed] +2008-07-07 v0.3 beta2 +增加UpdatePanelConnector控件,支持在布局构建的页面使用Asp.net Ajax。[fixed] -使用UpdatePanelConnector有一个要求:ContentTemplate下只能有一个子节点,比如box:Panel。 -示例在ajax3.aspx/content_page4.aspx。 -示例content_page3.aspx<em>中</em>,点击“Ajax查询”按钮和关闭弹出的窗口(点击右上角的叉)都引发异步更新。 +2008-07-03 v0.3 beta1 +容器控件的AutoHeight/AutoWidth默认为false。[fixed] -使用GroupPanel的地方需要手工添加AutoHeight="true"属性。 +增加UserControlConnector,可以在其<em>中</em>放置用户控件(示例在page_usercontrol.aspx)。[fixed] -也可以在ContentPanel<em>中</em>放置用户控件,注意两者的区别。 +增加ContentPlaceHolderConnector,替换原来Region的ContentPlaceHolderId属性(示例在Site.master)。[fixed] +支持Asp.net ajax异步加载。[fixed] -有很大局限性,只能在ContentPanel<em>中</em>使用,示例在ajax1.aspx/content_ajax2.aspx<em>中</em>。 -对于使用布局构建的页面(比如content_page1.aspx)还不能使用Asp.net ajax,因为页面是整体渲染的,先放弃。 +2008-07-02 v0.2 beta12 +关闭前提示当前页面已经被修改(示例在content_page1.aspx/simpleform.aspx)[fixed] -支持Iframe内按钮和window右上角关闭按钮。 -删除CloseAction属性,可以在后台通过OnClientCloseButtonClick属性指定(为了和iframe<em>中</em>做法一致)。 +iframe<em>中</em>的alert/confirm要覆盖整个父页面,而不仅仅是iframe页面。[fixed] -在Firefox下还有问题。[fix pending] +排序时在标题栏<em>显示</em>排序箭头,可以排序的列标题光标为手形(示例在grid_sorting.aspx)。[fixed] -可以通过设置Grid1.CurrentSortColumnIndex = 0;来强制某列<em>显示</em>排序箭头。 -可以通过 Grid1.Columns[Grid1.CurrentSortColumnIndex].SortExpression 的方式取得当前Grid的排序表达式。 +HyperLinkField/WindowField的链接地址支持服务器端格式(即是~/alert.aspx)。[fixed] -TabStrip的Tab<em>中</em>如果放置ContentPanel,则内容渲染位置不正确。[fixed] -可以在ContentPanel<em>中</em>放置用户控件(示例在page_usercontrol.aspx)。[fixed] +2008-06-30 v0.2 beta11 -增加TwinTriggerBox控件(示例在twintriggerbox.aspx)。[fixed] -Grid的<em>数据</em>库分页需要增加属性IsDatabasePaging=true,以便普通分页和<em>数据</em>库分页,否则在添加删除记录时总记录数不会变化 [feedback:zgjiang2]。[fixed] -关闭Window时PostBack事件OnClose可以指定参数,来区分是哪些操作引发的PostBack事件 [feedback:zgjiang2](示例在window_postback.aspx)。[fixed] -如果表单验证不通过,则需要弹出对话框提示(第一个没通过验证的字段)(目前还不能切换到相应的tab)。[fixed] +页面<em>中</em>任意可输入表单字段发生变化,可提示先保存。(示例在content_page1.aspx/simpleform.aspx)[fixed] -目前还不支持Window右上角关闭按钮的提示保存功能。 -Master/Content的内容页<em>中</em>Grid的Sort事件不起作用的BUG [feedback:zgjiang2]。[fixed] -Grid<em>中</em>的LinkButtonField设置ConfirmText会出错 [feedback:huihuang]。[fixed] -增加静态类Confirm。[fixed] +2008-06-27 v0.2 beta10 +Grid完善。[fixed] -CheckBoxField在回发时不能保持状态的BUG (已经更新了grid_checkboxfield.aspx示例)。 -Grid<em>中</em>模拟树<em>显示</em>,GridColumn增加DataSimulateTreeLevelField属性(一个Grid只能有一个Column指定此属性),指定此列模拟树<em>显示</em>时的层次字段(0,1,2,...)(示例在grid_simulate_tree.aspx)。 -切换分页时清空选<em>中</em>的值 [feedback:jqpeng]。 -增加PreRowDataBound事件,可以在<em>数据</em>绑定之前设置某列的属性 [feedback:xmzhu] (示例在grid_prerowdatabound.aspx)。 -DropDownList模拟树的方式<em>显示</em>,增加DataSimulateTreeLevelField属性,使用方法和Grid的类似(示例在dropdownlist_simulate_tree.aspx)。 +2008-06-25 v0.2 beta9 +Window窗体<em>中</em>的Iframe只让内容区域滚动,而Toolbar不滚动的规则。(示例在content_page2.aspx/simpleform.aspx)[fixed] -在simpleform.aspx<em>中</em>:Panel[BodyPadding=5](Toolbar,Panel[Height=450 Layout=Fit](SimpleForm[AutoScroll=true])),则外面窗口的高度=450 + 5*2 + 26 + 32,其<em>中</em>26是Toolbar的高度,32是窗口的标题栏和下边框的高度。 +关闭Iframe的LoadMask,所以需要Iframe页面添加PageLoading控件,这样效果统一。[fixed] +Grid完善。 -去除EnableClientPaging和EnableClientSort属性,客户端排序和客户端分页在ASP.NET应用<em>中</em>会有很多问题(主要是状态保持的问题)。 +EnableServerSort改名AllowSorting。(示例在grid_sorting.aspx) -使用非常简单:设置AllowSorting=true,注册OnSort事件,在事件处理函数<em>中</em>重新绑定<em>数据</em>。 +增加AllowPaging属性。(示例在grid_paging.aspx) -使用非常简单:设置AllowPaging=true,PageSize=3,注册OnPageIndexChange事件,在事件处理函数<em>中</em>Grid1.PageIndex = e.NewPageIndex;OK。 +<em>数据</em>库分页支持。(示例在grid_database_paging.aspx) -使用也非常简单:设置AllowPaging=true,PageSize=3,在绑定时设置RecordCount为总的记录数,在OnPageIndexChange事件处理函数<em>中</em>Grid1.PageIn</a></div><div data-report-view="{"mod":"popu_645","index":"3","dest":"https://download.csdn.net/download/sis_ying/477425","strategy":"2~default~OPENSEARCH~Rate","extra":"{\"utm_medium\":\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-3-477425-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\",\"dist_request_id\":\"1713920331325_95453\"}","spm":"1035.2023.3001.6557"}" class="list-item" data-v-ca2d15ac><div class="recommend-title" data-v-ca2d15ac><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAltJREFUWEdjZGBgYGhv/yD45//nEEYGBrX//xj4QWK0AoxMDB//MzDcYmHkXVNZKfCeEWz5v8/1DP8ZuGhlKVZzGRm+sTDxNjI2tz1OZfjHYEpXy2GWMTGcZmxpe9xN62DH5TlQdDA2tzyeNSC+h1o66gCyQyApUdRNSIhNGBSS7979ejtv/utd5EQl2Q7IypT0ExJiFoc44O/LadOfbxp1wPAOAWlpdr5Pn//8/Pzp70+QT3GlAX5+ZnYeHhb2p09/fiImRIhOhBYWvIo21ryWu/Z8PHDp4tdn2BxgoM8l4+IiYH/k6OdjJ058vk91B7g487swMDD8v3Hj+2VJSTYpfn5mEZAlHz/9ffPq5e+Xqqoc2iD+nr0f99DSAQQ9RhMHcHAwsYSGCtvKy7Gr4HPBo0c/b69c/fbwzx///hJ0KQMDA9FpAGaYizO/tpkZjwUTEyMTsgX//v3/d/LUl+N79368RozFMDUkOwCkUUODU8zHW9CFg4OJG8T/8ePf181b3u25efPHK1IsB6nF6gAjY25ZEWFWcNPs169/fw4c+HQD3WBBIRaOsBAhZ5D4qjXv9r5/9+cHuhoHBz4NNjYmFpD4m7e/P547+/UxuhqsDoiPE3WWlWVXgvju/5ee3qfLsfmMiZmBEST+7y/Df2zyJcXSkRwcjDwgucePf95buOj1Xqo6gFBwDw8H/P/P8O/nz//fCPkWmzw7OyMXIyMDOLeQHQXkWIxNz9BygJubgI6kBCu4tUMt8PzF75e7dn24QlQuoJalxJgzCDomA901G/DOKSieBrJ7DgCPdYFAskV/NwAAAABJRU5ErkJggg==" alt data-v-ca2d15ac> <a target="_blank" href="https://download.csdn.net/download/sis_ying/477425" data-report-click="{"mod":"popu_645","index":"3","dest":"https://download.csdn.net/download/sis_ying/477425","strategy":"2~default~OPENSEARCH~Rate","extra":"{\"utm_medium\":\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-3-477425-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\",\"dist_request_id\":\"1713920331325_95453\"}","spm":"1035.2023.3001.6557"}" data-report-query="spm=1035.2023.3001.6557&utm_medium=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-3-477425-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default&depth_1-utm_source=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-3-477425-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default" class="title" data-v-ca2d15ac>C#编程经验技巧宝典</a></div> <a target="_blank" href="https://download.csdn.net/download/sis_ying/477425" data-report-click="{"mod":"popu_645","index":"3","dest":"https://download.csdn.net/download/sis_ying/477425","strategy":"2~default~OPENSEARCH~Rate","extra":"{\"utm_medium\":\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-3-477425-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\",\"dist_request_id\":\"1713920331325_95453\"}","spm":"1035.2023.3001.6557"}" data-report-query="spm=1035.2023.3001.6557&utm_medium=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-3-477425-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default&depth_1-utm_source=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-3-477425-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default" class="desc" data-v-ca2d15ac>C#编程经验技巧宝典源代码,目录如下:第1章 开发环境 11.1 Visual Studio开发环境安装与配置 20001 安装Visual Studio 2005开发环境须知 20002 配置合适的Visual Studio 2005开发环境 20003 设置程序代码行序号 30004 开发环境全屏<em>显示</em> 30005 设置窗口的自动隐藏功能 30006 根据需要创建所需解决方案 40007 如何使用“验证的目标架构”功能 41.2 Visual Studio开发环境的使用 40008 为程序设置版本和帮助信息 40009 设置Windows应用程序启动窗体 50010 设置<em>Web</em>应用程序起始页 50011 如何设置程序的出错窗口 50012 如何进行程序调试 60013 如何结束不能正常运行的程序 60014 如何锁定窗体<em>中</em>的控件 60015 统一窗体<em>中</em>控件的字体设置 70016 通过“格式”菜单布局窗体 70017 起始页<em>中</em>的“Visual Studio开发人员新闻” 71.3 MSDN帮助的使用 80018 有效利用Visual Studio 2005附带程序 80019 有效使用MSDN帮助 90020 如何设置MSDN帮助 91.4 其他 100021 如何添加项目引用 100022 如何添加<em>Web</em>引用 100023 如何添加引用第3方控件 110024 如何生成DLL文件 110025 如何使用不安全代码 11第2章 语言基础 132.1 注释 140026 如何对代码进行注释 140027 #region、#endregion关键字的使用技巧 140028 “///”符号的使用技巧 140029 使用注释取消程序语句的执行 152.2 语句 150030 跳转语句GOTO的使用 150031 Continue语句的使用 160032 Break语句的使用 160033 Return语句的使用 170034 如何实现无限循环 170035 巧用foreach语句控制控件 180036 有效使用switch case语句 182.3 运算符 190037 如何使用引号赋值 190038 巧用“^=”运算符 190039 巧用位移运算符 200040 使用条件运算符 200041 巧用分隔符 200042 如何处理转义字符 210043 “;”结束符问题 210044 如何使用“??”操作符 222.4 表达式与关键词 220045 正确使用“&&”和“||” 220046 如何处理程序“溢出”错误 230047 有效使用base关键字 230048 typeof表达式的使用 230049 params关键字可以指定多参数 240050 using关键字的用法 240051 变量的作用域 252.5 其他 260052 有效使用this对象 260053 如何声明变量 260054 如何声明相同类型的多个变量 260055 利用Object变量传递参数 270056 强行改变运算符的运算顺序 27第3章 程序算法 293.1 <em>数据</em>结构 300057 如何实现单向链表 300058 如何实现双向链表 350059 如何实现堆栈 410060 队列的实现 430061 树的实现 443.2 排序 480062 如何实现选择排序算法 480063 如何实现冒泡排序算法 490064 如何实现快速排序算法 500065 如何实现插入排序算法 500066 如何实现希尔排序算法 513.3 常见算法的实际应用 520067 计算1+22+33+44+……+nn的值 520068 计算10!的值 520069 求最大公约数 520070 求最小公倍数 530071 判断素数的算法 530072 如何判断一个数是否是完数 540073 歌德巴赫猜想的算法 540074 八皇后问题 540075 用回溯法找出n个自然数<em>中</em>取r个数的全排列 550076 约瑟夫环问题 560077 猴子选大王 570078 如何判断IP是否正确 570079 如何将小写金额转换为大写金额 570080 统计文本字数 580081 文本<em>中</em>首字母改为大写 590082 C#随机数的产生 590083 身份证从15位升至18位算法 600084 十进制数转二进制数的算法 600085 十进制数转八进制数的算法 610086 十进制数转十六进制数的算法 620087 二、八、十六进制数转十进制数的算法 633.4 密码算法 650088 使用MD5算法对密码进行加密 650089 “凯撒”密码的算法 65第4章 字符及字符串处理技术 674.1 字符及字符串转换 680090 如何获得字母的ASCII码 680091 如何根据ASCII码获得字母 680092 编程<em>中</em>经常使用的ASCII码 680093 获得汉字的区位码 690094 如何根据区位码获得汉字 690095 如何将行字符串转换为列字符串 700096 如何将数字转换为字符串 700097 如何将字符串转换为数字 700098 如何将数字转换为日期格式 710099 如何将数字转换为货币格式 710100 将字母全部转换大写 710101 将字母全部转换小写 720102 将字符串首字母转换大写 720103 如何进行字节数组和字符串的相互转换 720104 如何把一个按空格分割的字符串存储在一个ArrayList数组<em>中</em> 734.2 获取字符串信息 730105 如何获得一个字符串的长度 730106 如何获得一个字符串<em>中</em>数字的长度 740107 如何获得字符串<em>中</em>数字或字母的长度 740108 如何获得字符串<em>中</em>某个数字的位置 750109 获得字符串<em>中</em>汉字的个数 760110 获得字符串<em>中</em>指定后几位字符 760111 计算字符串<em>中</em>子字符串出现的次数 760112 获得字符串<em>中</em>大写字母的个数 770113 获得某字符在字符串<em>中</em>最后出现的位置 780114 如何找出字符串<em>中</em>某一字符的所有位置 784.3 常用字符及字符串处理技术 790115 如何判断是否为数字 790116 如何在字符串<em>中</em>查找指定字符 790117 如何在字符串<em>中</em>用一子串替换另一子串 800118 将新字符串添加到已有字符串<em>中</em> 800119 如何在字符串<em>中</em>添加多个空格 810120 如何根据标点符号分行 810121 如何将字符串颠倒输出 820122 如何设置小数的保留位数 820123 如何对字符串进行组合或分解 820124 判断字符串<em>中</em>某一字符是否大写 830125 按要求生成指定位数编号 830126 确定两字符串是否相等 840127 判断两字符串<em>中</em>指定子串是否相等 840128 判断字符串是否为日期格式 850129 清除字符串<em>中</em>指定的字符 850130 复制字符串<em>中</em>指定的字符 850131 巧截字符串的数字 860132 如何存储变长字符串 860133 在进行字符串比较时忽略大小写 870134 如何去除字符串尾空格 870135 如何去掉字符串<em>中</em>所有空格 880136 如何进行文本加密与解密 880137 如何区别0、空字符串、Null、Empty和Nothing 890138 从字符串<em>中</em>分离文件路径、文件名及扩展名 890139 如何批量替换某一类字符串 89第5章 <em>数据</em>处理 915.1 数字处理技巧 920140 如何对计算结果四舍五放入 920141 如何将商品金额小写转换成大写 920142 如何根据生日自动计算员工年龄 930143 如何设置货币值<em>中</em>使用的小数位数 930144 如何自定义货币值<em>中</em>的小数点 940145 如何自定义货币值<em>中</em>小数点左边数字分组字符 940146 如何自定义货币值<em>中</em>小数点左边每一组的位数 950147 如何自定义百分比值<em>中</em>小数的位数 950148 如何自定义百分比小数点 960149 如何自定义百分比小数点左边数字分组字符 960150 如何自定义百分比小数点左边每一组的位数 970151 如何自定义百分比符号 970152 如何自定义数字小数点右边的保留位数 980153 如何自定义数字小数点左边分组位数 980154 格式化输入<em>数据</em>为货币格式 990155 如何计算两个整数的乘积 990156 如何将二进制数转换为十进制数 1000157 如何将二进制数转换为八进制数 1000158 如何将二进制数转换为十六进制数 1000159 如何实现0~9之间随机整数 1010160 如何实现0~1之间随机数 1010161 如何返回数字的绝对值 1015.2 控件<em>数据</em>处理技巧 1020162 如何实现C#<em>中</em>用键完成TAB的功能 1020163 如何限制文本框密码输入长度 1020164 <em>数据</em>输入为空提示 1030165 如何设置文本框光标到末尾 1030166 输入法调整技巧 1030167 锁定文本框内的文本 1030168 使用Message.Show输出用户信息 1045.3 图片<em>数据</em>处理技巧 1040169 如何将图片存入<em>数据</em>库 1040170 如何将图片从<em>数据</em>库<em>中</em>读取出来 1040171 如何只允许输入指定图片格式 1050172 如何设置录入图片统一图片大小 1055.4 数组处理技巧 1050173 如何转换数组类型 1050174 如何复制数组<em>中</em>一系列元素的元素 1060175 如何检索指定条件数组<em>中</em>的元素 1070176 如何动态改变数组长度 1080177 如何反转数组<em>中</em>元素的顺序 1080178 如何排序数组<em>中</em>的元素的顺序 1090179 如何创建动态数组 1105.5 NET应用技巧 1100180 如何使用ASP.NET技术对口令加密 1100181 如何设定ASP.NET全局变量 1110182 如何设定全局联接<em>数据</em>库对象 1110183 如何在ASP.NET<em>中</em>获得客户端IP地址 1110184 如何在ASP.NET<em>中</em>获取文件的扩展名 1110185 如何在ASP.NET<em>中</em>用URL在页面之间传值 1120186 如何使用IsPostBack实现ASP.NET页面加载 1120187 如何利用输出缓存技术缓存ASP.NET页面 1120188 如何在ASP.NET<em>中</em><em>显示</em>当前IE浏览器头信息 1135.6 其他应用技巧 1140189 如何判断年份是否为闰年 1140190 如何根据年份判断十二生肖 1140191 如何根据IP地址获取本机域名 1150192 如何获取“我的文档”系统文件夹路径 1150193 如何获取应用程序当前执行的路径 1160194 如何获取当前操作系统的信息 1160195 如何实现基本<em>数据</em>类型随意转换 1160196 如何生成全局唯一标识符(GUID) 118第6章 资料验证技术 1196.1 网络验证应用技巧 1200197 如何使用正则表达式验证E-mail格式 1200198 如何使用正则表达式验证IP地址 1200199 如何使用正则表达式验证URL 1206.2 常用数字验证技巧 1210200 如何使用正则表达式验证电话号码 1210201 如何使用正则表达式验证输入密码条件 1210202 如何使用正则表达式验证邮政编号 1210203 如何使用正则表达式验证手机号 1220204 如何使用正则表达式验证身份证号 1220205 如何使用正则表达式验证两位小数 1220206 如何使用正则表达式验证一年的12个月份 1230207 如何使用正则表达式验证一个月的31天 1230208 如何使用正则表达式验证数字输入 1230209 如何使用正则表达式验证密码长度 1240210 如何使用正则表达式验证非零的正整数 1240211 如何使用正则表达式验证非零的负整数 1246.3 常用字符验证技巧 1250212 如何使用正则表达式验证大写字母 1250213 如何使用正则表达式验证小写字母 1250214 使用正则表达式检查字符串<em>中</em>重复出现的词 1250215 如何使用正则表达式替换字符串 1260216 如何使用正则表达式拆分字符串 1270217 如何使用正则表达式验证输入字母 1270218 如何使用正则表达式验证<em>中</em>文汉字输入 1280219 如何使用正则表达式验证输入字符串 128第7章 日期和时间 1297.1 日期与时间的获取 1300220 获得系统当前日期 1300221 获得系统当前时间 1300222 同时获得系统当前日期和时间 1300223 如何获取当前日期是星期几 1300224 如何获取当前年的天数 1310225 如何获取当前月的天数 1310226 如何取得当前日期的前一天 1320227 使用TimeSpan对象获取时间间隔 1337.2 日期的格式化及其时间的比较 1330228 将日期格式化为指定格式 1330229 如何将短日期格式化为长日期格式 1340230 如何将数字日期转化为<em>中</em>文格式 1340231 如何对系统时间和数字进行比较 1350232 如何比较时间 1350233 获取两个日期之间的时间差并进行比较 1367.3 日期方法与函数的应用 1360234 使用DateDiff方法获取日期时间的间隔数 1360235 在SQL语句<em>中</em>使用DATEADD函数向指定日期添加一段时间间隔 1370236 在SQL语句<em>中</em>使用DATEDIFF函数获得两个日期的间隔 1370237 如何使用Sleep方法延迟时间 1370238 如何确定程序的运行时间 1380239 如何使用ParseExact方法将字符串转化为日期格式 1380240 如何使用ToString方法格式化日期 1390241 如何使用Convert方法转换日期<em>显示</em>格式 1397.4 系统时间与日期的设置 1400242 如何设置系统的日期 1400243 如何设置系统的时间 1400244 如何设置系统的日期和时间 1417.5 日期与时间的应用 1420245 如何将<em>数据</em>控件<em>中</em>的日期以编程的方式转化为指定格式 1420246 将格式化日期的方法绑定到<em>数据</em>控件<em>中</em> 1420247 直接格式化绑定到<em>数据</em>控件GridView<em>中</em>的日期列 1430248 在<em>数据</em>控件GridView的RowDataBound事件<em>中</em>对绑定到GridView控件的日期列进行格式化 1430249 如何实现倒计时功能 1430250 如何创建一个数字时钟 144第8章 Windows窗体设计 1458.1 Windows窗体基本操作 1460251 控制窗体加载时所在的位置 1460252 控制窗体最大化、最小化 1460253 清空窗体<em>中</em>的图片 1460254 如何使程序窗体总在最前 1470255 如何将菜单置于窗体的左侧 1470256 将其他窗体作为当前窗体的子窗体 1470257 如何根据控件大小自动<em>显示</em>滚动条 1480258 如何<em>显示</em>About窗体 1480259 利用Show方法<em>显示</em>被调用窗体 1490260 Load事件将窗体加载到内存 1490261 窗体的卸载与隐藏 1490262 设置窗体的状态 1490263 如何设置窗体在桌面上的位置 1500264 如何在关闭窗体前<em>显示</em>确认对话框 1500265 如何去掉窗体的标题栏 1510266 如何禁止在任务栏<em>中</em><em>显示</em>窗体标题 1520267 如何禁止缩放窗体的边框 1520268 如何设置窗体标题栏文字右对齐 1520269 如何<em>显示</em>窗体的属性信息 1530270 如何隐藏窗体标题栏的按钮 1538.2 Windows窗体高级操作 1530271 设置闪烁的标题栏 1530272 如何在托盘<em>中</em>写入应用程序图标 1540273 如何以全屏方式<em>显示</em>程序窗体 1540274 如何从上次关闭位置启动窗体 1540275 如何通过拖动工作区来移动窗体 1550276 如何渐变<em>显示</em>窗体背景颜色 1550277 如何排列MDI窗体<em>中</em>的子窗体 1560278 如何拖动无标题栏窗体 1578.3 特殊类型的窗体 1580279 创建一个无ICON的窗体 1580280 如何制作飘动的窗体 1580281 使用拆分窗口 1590282 用C#实现启动欢迎界面 1590283 如何实现半透明渐显窗体 1600284 基于ListView的导航界面 1600285 类似OutLook的导航界面 1620286 图形化的导航界面 1620287 如何实现类似QQ的程序界面 1620288 如何实现类似Windows XP的程序界面 1640289 制作字形窗体 1640290 制作图形窗体 1640291 随机更换背景的窗体 1658.4 菜单、工具栏和状态栏的设计 1660292 带图标的菜单 1660293 带历史信息的菜单 1660294 可以拉伸的菜单 1670295 带背景的工具栏 1680296 浮动工具栏 1680297 带下拉菜单的工具栏 1690298 在状态栏<em>中</em><em>显示</em>复选框 1690299 带进度条的状态栏 1690300 带图标的状态栏 1708.5 其他 1700301 界面设计要素 1700302 界面设计在程序开发<em>中</em>的重要性 1710303 如何设置窗体的键响应按钮 1720304 如何设置窗体的键响应按钮 1720305 窗体间<em>数据</em>的访问 172第9章 Windows窗体控件 1759.1 TextBox控件应用技巧 1760306 文本框<em>中</em>只能输入数字 1760307 如何设置TextBox控件输入多行文本 1760308 如何锁定文本框 1760309 如何控制TextBox控件<em>中</em>的插入点 1760310 如何创建密码文本框 1770311 如何创建只读文本框 1770312 如何在文本框字符串<em>中</em>放置引号 1770313 如何在TextBox控件<em>中</em>查看多个行 1770314 如何TextBox控件<em>中</em><em>显示</em>回车符 1789.2 RichTextBox控件应用技巧 1780315 删除RichTextBox控件<em>中</em>的部分文字 1780316 RichTextBox与TextBox控件有何不同 1790317 如何使用RichTextBox控件<em>显示</em>文件 1790318 如何使用RichTextBox控件保存文件 1800319 如何在RichTextBox控件<em>中</em>查找字符 1810320 如何在RichTextBox控件插入图片 1810321 如何为RichTextBox控件添加快捷菜单 1820322 在RichTextBox控件<em>中</em>替换文本文字 1839.3 Button控件应用技巧 1830323 C#<em>中</em>轻松打造绚丽按钮 1830324 如何使Button控件大小自动适应文本长度 1840325 如何设置窗体一个默认单击按钮 1840326 如何设置窗体一个默认取消按钮 1840327 如何给按钮控件创建快捷键 1850328 如何触发Button按钮的Click事件 1850329 使用控件的Tag属性传递信息 1850330 如何在Windows窗体上停靠控件 1860331 如何动态创建Button控件 1869.4 DataGridView控件应用技巧 1870332 如何对DataGridView控件进行<em>数据</em>绑定 1870333 如何在DataGridView控件<em>中</em>设置<em>数据</em>的格式 1870334 如何在DataGridView控件基于文本的单元格<em>中</em>启用换行 1870335 如何设置DataGridView控件单元格的文本对齐方式 1870336 如何在DataGridView控件<em>中</em>验证<em>数据</em>输入 1880337 DataGridView控件<em>中</em>输入<em>数据</em>时发生的错误 1880338 如何设置DataGridView控件<em>中</em>网格线的样式 1890339 如何设置DataGridView控件<em>中</em>的边框样式 1890340 如何设置DataGridView控件<em>中</em>字体样式 1900341 如何设置DataGridView控件<em>中</em>颜色样式 1900342 获取DataGridView控件<em>中</em>单元格、行和列坐标 1900343 如何获取DataGridView控件<em>中</em>的当前单元格 1910344 如何禁止DataGridView控件<em>中</em>添加和删除行 1910345 DataGridView控件选<em>中</em>单元格时整个行背景变色 1910346 如何复制DataGridView控件单元格<em>中</em>的<em>数据</em> 1910347 如何在DataGridView控件实现下拉列表 1929.5 对话框控件应用技巧 1920348 如何利用FontDialog控件设置字体 1920349 如何利用ColorDialog控件设置字颜色 1930350 如何利用OpenFileDialog控件打开文件 1930351 如何获得弹出对话框的相关返回值 1940352 使用FolderBrowserDialog控件选择文件夹 1959.6 ListBox控件应用技巧 1950353 如何快速选<em>中</em>ListBox控件<em>中</em>全部条目 1950354 如何排序ListBox控件<em>中</em>的<em>数据</em> 1960355 如何实现ListBox控件的多项选择功能 1960356 如何在ListBox控件<em>中</em>查找指定的项 1960357 实现ListBox控件与ListBox控件交换<em>数据</em> 1979.7 ListView控件应用技巧 1980358 如何实现ListView控件实现动态加载<em>数据</em> 1980359 如何向ListView控件添加搜索功能 1990360 如何将<em>数据</em><em>中</em>的表内容填充到ListView控件<em>中</em> 2000361 如何使ListView控件拥有编辑功能 2010362 如何实现ListView控件<em>显示</em>图标与列表 2010363 如何获取ListView控件<em>中</em>的选择结果 2020364 如何将图片加载ListView控件 2029.8 TreeView控件应用技巧 2030365 如何在TreeView控件结点<em>中</em><em>显示</em>图片 2030366 如何在TreeView控件<em>中</em>用鼠标右键选<em>中</em>节点 2030367 区分TreeView控件选<em>中</em>各节点方式 2040368 如何实现TreeView控件节点拖放操作 2040369 如何实现带复选框的TtreeView控件 2050370 如何实现TreeView控件遍历磁盘目录 2060371 如何将<em>数据</em>库字段填充到TreeView控件 2069.9 ComboBox控件应用技巧 2070372 如何使ComboBox下拉列表<em>显示</em>图片 2070373 ComboBox只能从下拉列表框<em>中</em>选择<em>数据</em> 2080374 如何实现带查询功能的ComboBox控件 2080375 如何实现文件目录名称填充ComboBox控件 2090376 如何将数组绑定到ComboBox控件 2100377 如何将<em>数据</em>库字段绑定到ComboBox控件 2109.10 组件应用技巧 2110378 如何使用ProgressBar控件<em>显示</em>操作的进度 2110379 如何使用ToolTip控件<em>显示</em>提示信息 2110380 如何使用FlowLayoutPanel控件布局窗体 2120381 如何使用SplitContainer控件分隔窗体 2130382 如何使用Process组件打开系统进程 2140383 FileSystemWatcher监视文件夹内文件的更改 2149.11 其他常用件控件应用技巧 2150384 如何在状态栏<em>中</em><em>显示</em>时间 2150385 如何在状态栏<em>中</em>加载图片 2150386 如何设置DateTimePicker控件<em>显示</em>为空文 2150387 如何判断ToolStrip控件Button控钮的单击 2150388 如何实现Panle自动调整大小充满窗体 2160389 如何实现CheckedListBox控件选重所有项 2160390 如何实现CheckBox控件的选择状态 2160391 如何使Lable控件<em>显示</em>出多行文字 2170392 如何使用LinkLabel控件实现超级链接 2170393 如何设置MaskedTextBox控件输入验证 2180394 如何使用NotifyIcon控件创建任务托盘 2190395 如何控制PictureBox控件<em>显示</em>图片风格 219第10章 <em>Web</em>页面设计 22110.1 网页外观设计 2220396 将CSS样式表应用到页面<em>中</em> 2220397 在页面的源码<em>中</em>直接定义样式表 2220398 动态加载主题到页面<em>中</em> 2230399 利用Table布局<em>Web</em>页面 2230400 FrameSet框架的应用 2240401 IFrame框架的应用 2240402 页面尺寸自动适应1024×768像素和800×600分辨率 22510.2 网页性能设计 2250403 用meta标签来增强网页性能 2250404 什么情况下使用缓冲会提高速度 2260405 使用OutputCache指令实现页面缓存 2260406 设置网页缓存的位置 2270407 使用Cache类实现应用程序<em>数据</em>缓存 2270408 缓存网页的不同版本 22710.3 <em>Web</em>页的绑定 2280409 如何绑定变量 2280410 如何绑定集合 2280411 如何绑定表达式 2290412 如何绑定方法结果 2300413 巧用DataBinder.Eval()方法进行<em>数据</em>绑定 2300414 如何将DropDownList控件绑定到GridView控件<em>中</em> 23110.4 开发<em>Web</em>页的常用功能 2310415 使用QueryString变量在页面之间传值 2310416 页面定时刷新如何实现 2320417 <em>显示</em>只有数字的验证码图片 2320418 <em>显示</em>数字和英文字母组合的验证码图片 2320419 页面定时刷新后跳转到其他页 2330420 打开新的窗口并传送参数 2330421 动态<em>显示</em>用户头像 2330422 利用Pannel控件<em>显示</em>和隐藏一组控件 2330423 如何在GridView控件上添加删除确认 2340424 如何为GridView控件添加编号列 2340425 FindControl方法的应用 2340426 如何实现单击表格行打开另一页并传递参数 2350427 如何实现双击表格行超级链接到另一页并传递参数 2350428 如何实现单击表格行改变颜色 2350429 鼠标移动改变表格行的颜色 2350430 如何在<em>Web</em>页<em>中</em>使用表格控件 23610.5 <em>Web</em>.Config文件的配置 2370431 通过Encoding的设置实现页面无乱码 2370432 限制上传文件大小与时间 2370433 配置验证级别 23710.6 开发<em>Web</em>页其他功能 2380434 如何使Pannel实现横向滚动纵向自动扩展 2380435 属性MaintainScrollPositionOnPostBack实现网页定位 2380436 自动隐藏式菜单 2380437 关闭弹出窗口刷新父窗口 2390438 弹出网页模式对话框 2400439 弹出全屏<em>显示</em>网页 2410440 为什么要生成静态页 2420441 用快捷键+实现屏蔽 2420442 如何在<em>Web</em>页<em>中</em>使用广告控件 2420443 滚动<em>显示</em>博客公告 243第11章 HTML客户端控件与服务器控件 24511.1 <em>数据</em>控件应用技巧 2460444 如何将数组绑定到GridView<em>数据</em>控件<em>中</em> 2460445 使用GridView <em>Web</em>服务器控件绑定<em>数据</em>源 2460446 使用GridView <em>Web</em>服务器控件自定义外观风格 2470447 使用GridView <em>Web</em>服务器控件的简单排序 2470448 如何在GridView <em>Web</em>服务器控件<em>中</em>分页 2480449 使用GridView <em>Web</em>服务器控件编辑<em>数据</em> 2490450 使用GridView <em>Web</em>服务器控件删除<em>数据</em> 2510451 如何使用GridView <em>Web</em>服务器控件选择<em>数据</em> 2520452 单击GridView控件按钮刷新保持原来的位置 2530453 向GridView <em>Web</em>控件<em>中</em>添加CheckBox控件 2530454 如何使用GridView <em>Web</em>控件实现超级链接 2540455 在GridView <em>Web</em>控件<em>中</em>高亮<em>显示</em>鼠标所在行 2560456 实现DataList <em>Web</em>服务器控件<em>数据</em>绑定功能 2560457 如何实现DataList <em>Web</em>服务器控件分页功能 2580458 实现查看DataList控件<em>中</em><em>数据</em>的详细信息 2590459 如何在DataList控件<em>中</em>创建多个列 2600460 如何实现DetailsView 控件分页功能 2610461 将DataSet类对象绑定到Repeater<em>数据</em>控件<em>中</em> 26211.2 导航控件应用技巧 2630462 TreeView、SiteMapDataSource控件和SiteMap文件实现导航 2630463 如何在TreeView控件<em>中</em>添加连接线 2640464 以编程方式向TreeView控件<em>中</em>添加节点 2640465 如何在TreeView控件<em>中</em><em>显示</em>CheckBox控件 2650466 如何判断TreeView控件<em>中</em>被勾选的节点 2650467 用SiteMapPath控件绑定SiteMap文件实现导航 2660468 如何设置SiteMapPath控件路径分隔符 2660469 如何设置SiteMapPath控件路径方向 2670470 如何设置SiteMapPath控件父节点<em>显示</em>个数 2670471 如何设置SiteMapPath控件提示字符 2680472 如何用Menu控件绑定SiteMap文件实现导航 2680473 如何设置Menu控件<em>显示</em>静态菜单 2690474 如何以编程方式创建Menu控件 27011.3 标准控件应用技巧 2710475 使用HyperLink服务器控件实现页面间传值 2710476 如何使用Input(Reset)实现文本框清空功能 2710477 如何取消DropDownLidt控件的激发验证 2720478 使用FileUpload服务器控件实现文件上传 2720479 使用LinkButton服务器控件实现超级链接 2730480 实现DropDownList服务器控件的<em>数据</em>绑定 2730481 如何改变DropDownList服务器控件<em>中</em>的项 2740482 指定ListBox服务器控件<em>中</em>的项的目的移位顺序 2750483 响应ListBox服务器控件的改变事件 2760484 如何使用CheckBox服务器控件 2760485 如何使用CheckBoxList服务器控件 2770486 使用RadioButtonList服务器控件巧用单项选择 2780487 使用BulletedList控件<em>显示</em>项目符号和编号 2790488 如何使用HiddenField控件 2800489 如何使用Literal控件<em>显示</em>静态文本 2810490 如何使用AdRotator控件制作广告 2810491 如何使用Wizard <em>Web</em>服务器控件制作导航页 2820492 使用XML服务器控件转换XML文档 2830493 使用MultiView与View控件制作导航页面 2860494 使用PlaceHolder控件实现动态添加控件 2890495 如何实现带滚动条的Panel面板 2900496 使用Substitution控件在缓存页面插入内容 290第12章 内置对象 29312.1 ASP.NET基本对象 2940497 使用Session对象在页面之间传值 2940498 如何使用Session验证用户登录 2940499 配置Session的生命周期 2940500 如何遍历Session对象 2950501 使用Application对象在页面之间传值 2950502 存取Application变量内容 2950503 如何锁定Application对象 2960504 如何使用Application实现站点访问量统计 2960505 如何删除Application变量内容 2960506 使用ViewState对象在同一个页面传值 29712.2 Response与Request对象 2970507 如何解决Response.Redirect方法传递汉字时出现的错误 2970508 使用Response.BinaryWrite方法输出二进制图像 2970509 Response对象将文本文件的内容写回客户端浏览器 2980510 如何使用Request接收页面间传值 2980511 使用Request对象的Browser属性获取客户端浏览器信息 2980512 获取客户端和服务器端IP地址 2990513 使用Request对象获取客户端的表单信息 3000514 使用Request对象的PhysicalApplicationPath属性获取服务器的绝对路径 3000515 使用Request对象的CurrentExecutionFilePath属性获取当前页面的路径 3000516 如何获取ASP.NET<em>中</em>所有Request的属性 3000517 缓存区的应用 30112.3 Cookie对象 3020518 使用Cookie的优缺点 3020519 使用Cookie对象在页面之间传值 3020520 如何使用Cookie验证用户登录 3030521 Cookie可以存储哪些值 3030522 使用Cookie对象保存和读取客户端信息 3030523 如何加密Cookie<em>中</em>的<em>数据</em> 3040524 创建及存取多个键值的Cookie对象 3040525 如何遍历Cookie集合 3040526 设定Cookie变量的生命周期 3050527 如何删除客户端的Cookies 3050528 如何删除多值Cookie<em>中</em>的某个值 3050529 如何使用Cookie处理网上重复投票 3050530 如何使用户第2次访问我的网站不用提交信息 30612.4 Server对象 3070531 使用Server.Transfer方法在页面之间传值 3070532 使用Server.MapPath方法获取服务器的物理地址 3080533 使用Server.UrlEncode方法对字符串进行编码 3080534 使用Server.UrlDecode方法对字符串进行解码 3080535 利用Server对象进行HTML编码输出 3080536 利用Server对象进行HTML解码输出 309第13章 图形图像技术 31113.1 图像预览及转换 3120537 如何设计缩略图功能的图片浏览器 3120538 如何浏览大图片 3120539 如何局部放大图片 3130540 如何实现剪切图片 31313.2 图形缩放与变换 3150541 如何缩放图片 3150542 如何转换图像文件格式 31513.3 图像效果 3160543 如何以底片效果<em>显示</em>图像 3160544 如何以浮雕效果<em>显示</em>图像 3170545 如何以黑白效果<em>显示</em>图像 3180546 如何以柔化效果<em>显示</em>图像 3190547 如何以锐化效果<em>显示</em>图像 3200548 如何以雾化效果<em>显示</em>图像 3210549 如何以光照效果<em>显示</em>图像 3220550 如何以百叶窗效果<em>显示</em>图像 3230551 如何以马赛克效果<em>显示</em>图像 3250552 如何以任意角度旋转图像 3260553 如何以椭圆形<em>显示</em>图像 3270554 如何以不同的透明度<em>显示</em>图像 3280555 如何以不同分辨率<em>显示</em>图像 3280556 如何以不同翻转方式<em>显示</em>图像 3290557 如何以油画效果<em>显示</em>图像 3300558 如何以扭曲效果<em>显示</em>图像 3310559 如何以分块效果<em>显示</em>图像 3320560 如何以四周扩散方式<em>显示</em>图像 3330561 如何以从上向下拉伸方式<em>显示</em>图像 3340562 如何以从左向右拉伸方式<em>显示</em>图像 3350563 如何以上下反转方式<em>显示</em>图像 3350564 如何以上下对接方式<em>显示</em>图像 3360565 如何以左右反转方式<em>显示</em>图像 3370566 如何以左右对接方式<em>显示</em>图像 3380567 如何以淡入淡出效果<em>显示</em>图像 3390568 如何以积木效果<em>显示</em>图像 34113.4 图像字体 3420569 如何以渐变色效果<em>显示</em>文字 3420570 如何以倾斜效果<em>显示</em>文字 3430571 如何以阴影效果<em>显示</em>文字 3430572 如何以倒影效果<em>显示</em>文字 3440573 如何以投影效果<em>显示</em>文字 3440574 如何以浮雕效果<em>显示</em>文字 3450575 如何以印版效果<em>显示</em>文字 3460576 如何为文字填充图片纹理 3460577 如何创建可旋转文字 34713.5 图像识别及图像工具 3470578 如何获取图像的像素值 3470579 如何设置图像的像素值 3480580 如何校正图像<em>显示</em>颜色 3490581 如何使用阈值校正图像<em>显示</em>颜色 3510582 如何获得图像信息 3520583 如何制作简单的画图工具 3530584 如何将图片以Image类型存储到<em>数据</em>库 3560585 如何从<em>数据</em>库<em>中</em>读取Image类型的字段 35713.6 图像应用及其他 3580586 如何在<em>Web</em>页面上<em>显示</em>图像 3580587 绘制渐变背景图像 3590588 确定鼠标是否在图形范围内 3590589 如何绘制柱形图 3600590 如何绘制饼形图 3620591 如何绘制折线图 3640592 如何绘制图形验证码 3660593 如何在桌面上全屏<em>显示</em>图像 3670594 如何利用Image制作小动画 3680595 如何使用鼠标拖动图片 3680596 如何获取当前鼠标的形状 369第14章 动画与多媒体 37114.1 声音控制 3720597 如何播放WAV声音文件 3720598 如何播放默认的Beep事件声音 3720599 如何播放默认的Hand事件声音 3720600 如何播放默认的Asterisk事件声音 3720601 如何播放默认的Question事件声音 3730602 如何播放默认的Exclamation事件声音 3730603 如何设置计算机喇叭发出的声音 3730604 如何同步加载并播放声音文件 3740605 如何异步加载并播放声音文件 37414.2 多媒体及其他 3750606 C#实现动画效果 3750607 C#设计屏幕保护程序 3750608 如何实现滚动字幕 3760609 如何播放AVI动画文件 3760610 如何播放Flash 3770611 用C#实现家庭影集 3780612 C#实现电影特效 3790613 如何实现Word艺术字 3790614 检查是否安装声卡 3800615 带有记忆功能的MP3 3800616 打开和关闭光驱 3810617 如何收听网络电台 3820618 如何通过剪贴板复制粘贴图像 3820619 如何转换图像文件的保存格式 3830620 如何制作自动播放的MP3播放器 3840621 学校体操定时音乐播放 3850622 如何从ARGB分量值创建Color结构 3850623 如何动画<em>显示</em>窗体 3860624 如何获取系统的图像编码器信息 3870625 如何获取系统的图像解码器信息 388第15章 键盘与鼠标 38915.1 鼠标操作技巧 3900626 鼠标双击窗体时模拟键盘Tab键操作 3900627 定义鼠标指针形状 3900628 自定义鼠标的图片 3910629 鼠标拖放复制文本 3910630 如何使用鼠标单击添加控件 3920631 如何获得鼠标在窗体上的位置 3920632 如何交换鼠标左右键功能 3920633 如何隐藏和<em>显示</em>鼠标 3930634 如何获取光标闪烁的频率 3940635 如何获得屏幕上鼠标的坐标 3940636 如何限制鼠标在某一区域工作 3940637 如何利用鼠标绘图 3950638 如何获取鼠标双击时间间隔 3960639 如何获取鼠标键数 3960640 如何<em>显示</em>鼠标的等待光标 3970641 如何禁用鼠标左键 3970642 如何模拟鼠标操作 3980643 如何实现鼠标穿透窗体 3990644 如何记录鼠标行为 39915.2 键盘操作技巧应用 4000645 如何禁用输入法编辑器 4000646 如何打开和关闭输入法编辑器 4000647 回车转换成Tab键 4000648 如何获取组合键 4010649 如何获取功能键 4010650 如何判断NumLock键和CapsLock键是否锁定 4010651 如何屏蔽+键关闭窗体 4020652 如何实现按下键关闭窗体 4020653 如何避免按键产生“嘀”声 4030654 如何设置键盘热键 403第16章 文件、文件管理及<em>数据</em>流 40516.1 获取文件基本信息 4060655 获取文件创建的日期和时间 4060656 如何检索路径<em>中</em>的文件名和扩展名 4060657 如何获得文件的大小 4070658 如何修改文件属性 4070659 如何监视文件系统变化情况 4080660 如何获取文件的系统启动方式 4080661 如何获取文件名禁止使用的字符 4090662 如何获取路径名禁止使用的字符 4100663 如何获取指定目录的上级目录 41016.2 文件基本操作 4110664 判断文件是否存在 4110665 创建一个文件用于写入UTF-8编码的文本 4110666 OpenRead方法打开现有文件并读取 4120667 打开现有UTF-8编码文本文件并进行读取 4120668 OpenWrite方法打开现有文件并进行写入 4130669 如何读取文件<em>中</em>的第一行<em>数据</em> 4130670 如何向文件<em>中</em>写入<em>数据</em> 4130671 如何读取文件<em>中</em>所有<em>数据</em> 4140672 如何创建临时文件 4140673 如何实现文件替换 4150674 使用递归法删除文件夹<em>中</em>所有文件 4150675 如何更改文件扩展名 4160676 如何实现复制文件 4160677 如何修改文件名 4160678 如何删除文件 4170679 如何上传文件 4170680 如何下载文件 4180681 如何拖放文件 4190682 如何搜索文件 41916.3 文件夹基本操作 4200683 如何创建文件夹 4200684 如何移动文件夹 4200685 如何修改文件夹名称 4210686 如何遍历文件夹 4210687 如何删除文件夹 42216.4 <em>数据</em>流操作 4220688 如何读写内存<em>数据</em>流 4220689 如何创建二进制文件 4230690 如何读取二进制文件 4230691 如何使用缓冲流 42416.5 加密、解密及解压缩文件 4250692 加密和解密文件 4250693 如何使用对称算法加密文件 4250694 如何使用对称算法解密文件 4260695 如何使用GZip压缩文件 4270696 如何使用GZip解压文件 4280697 如何使用WinRAR压缩文件 4290698 如何使用WinRAR解压文件 42916.6 其他 4300699 设置文件的访问模式 4300700 如何在C#应用程序<em>中</em>使用INI文件 4300701 如何操作帮助文件 4310702 如何操作Word文件 4320703 如何操作Excel文件 4330704 如何将文本文件转换成网页文件 4340705 如何产生随机文件夹名或文件名 4350706 如何将长文件名转换成短文件名 4360707 如何用程序创建XML文档并写入内容 4360708 如何通过DataSet对象读取XML文件 4380709 如何动态创建XML文件节点 4390710 如何实现XML文件<em>数据</em>类型的转换 4390711 将图片保存到XML文件<em>中</em> 4400712 如何比较两个文件的内容是否相同 4400713 如何以缩略图形式上传图片文件 4410714 如何解析只有一种格式的文本文件 4420715 如何解析含有多种格式的文本文件 443第17章 Windows开发技术 44517.1 获取计算机系统信息 4460716 如何获取系统时间 4460717 如何获取系统目录 4460718 如何获取计算机名称 4460719 如何获取当前程序运行目录 4460720 如何获得操作系统版本号 44617.2 获取计算机硬件信息 4460721 如何获取CPU编号 4460722 如何获取<em>显示</em>设备的PNPDeviceID 4470723 如何获取声音设备的PNPDeviceID 4470724 如何获取硬盘编号 4470725 如何获取CPU的版本信息 4480726 如何获取CPU的产品名称信息 4480727 如何获取CPU的制造商名称 4480728 如何获取主板制造商 4490729 如何获取主板编号 4490730 如何获取主板型号 4490731 如何获取磁盘空间 4500732 如何获取磁盘剩余空间 4500733 如何确定屏幕的分辨率 4510734 如何获得磁盘的卷标 4520735 如何获得磁盘的文件系统类型 45217.3 获取特殊文件夹路径 4530736 如何获取ProgramFiles目录全路径 4530737 如何获取桌面目录全路径 4530738 如何获取开始菜单目录全路径 4540739 如何获取用户程序组目录全路径 4540740 如何获取文档模板目录全路径 4550741 如何获取收藏夹目录全路径 4550742 如何获取共享组件目录全路径 4560743 如何获取我的图片目录全路径 4560744 如何获取Internet历史记录全路径 4570745 如何获取Internet临时文件目录全路径 4570746 如何设置可用样式 45717.4 获得Windows当前用户 4580747 如何获取当前用户 4580748 如何判断当前用户是否是普通用户 4580749 如何判断当前用户是否是超级用户 4580750 如何判断当前用户是否是系统管理员 4590751 如何判断当前用户是否是系统操作员 4590752 如何判断当前用户是否是备份操作员 4600753 如何判断当前用户是否是打印操作员 4600754 如何判断当前用户是否是复制程序员 4610755 如何判断当前用户是否是账户操作员 46117.5 Windows日志 4620756 如何获取系统日志信息 4620757 如何获取安全日志信息 4620758 如何获取应用程序日志信息 4630759 如何创建并写入自定义日志信息 4640760 如何向系统日志写入自定义<em>数据</em> 4640761 如何向应用程序日志写入自定义信息 46517.6 计算机控制 4650762 列举系统<em>中</em>所有窗口 4650763 C#实现键盘钩子 4650764 如何关闭计算机 4660765 如何抓屏 4660766 如何休眠计算机 4670767 如何禁止使用Windows任务管理器 4680768 如何为文件新增右键菜单项 4680769 如何设置系统仅能运行的程序 4690770 如何获取本地计算机上所有的进程 4690771 如何启动一个进程 4700772 怎样杀死一个进程 4700773 如何获取远程计算机上所有的进程 47017.7 其他相关技术 4700774 如何在注册表<em>中</em>保存窗体的大小和位置 4700775 如何实现程序间注册表内传递变量 4710776 在使用OpenFileDialog<em>中</em>的相对路径问题 4710777 如何设置启动时自动执行程序 4710778 C#编程实现Windows XP风格的界面 4710779 用C#实现文件查找功能 4730780 如何序列化对象 4730781 如何实现特殊形状的窗体 4740782 如何移动正在使用的文件 4740783 如何实现类似QQ的程序界面 4750784 如何实现动画<em>显示</em>窗体 4760785 如何<em>显示</em>和隐藏任务栏 4770786 如何实现OutLook界面 4780787 如何在C#<em>中</em>回车换行 4780788 如何获取进程的命令行 4790789 如何按行读取文本并<em>显示</em>行数 4790790 如何在Form<em>中</em>嵌入Excel 4790791 如何使用互斥量禁止程序运行两个实例 4800792 如何使用进程名禁止程序运行两个实例 4800793 如何获取控制台应用程序的<em>显示</em>结果 4810794 如何用@代替路径<em>中</em>的转义字符 482第18章 程序应用控制 48318.1 提取信息 4840795 判断驱动器类型并获取其属性 4840796 如何得到本地机器的IP 4840797 如何得到本地运行的EXE的路径 4850798 得到计算机所有正在运行的进程 4850799 获得Windows的启动模式 4850800 获取鼠标的按钮个数及鼠标安装状态 4850801 检测计算机是否存在网络连接 4860802 如何判断计算机的联机状态 4860803 获取计算机屏幕分辨率 4860804 获取计算机当前登录的用户名称 48618.2 系统控制 4860805 远程关闭或重新启动计算机 4860806 创建应用程序快捷方式 4870807 启动Windows系统服务 4880808 在C#应用程序<em>中</em>控制输入法 4880809 打开“区域和语言选项”对话框并指定选项卡 4890810 如何执行命令行命令? 4890811 如何修改计算机的默认打印机 4900812 如何实现行业软件系统注销功能 4900813 如何将计算机设置为休眠状态 4900814 在Windows系统<em>中</em>建立事件日志 4910815 如何使PC喇叭发音 49118.3 程序控制 4910816 使用回车键控制鼠标焦点 4910817 如何调用可执行应用程序 4920818 TextBox上禁用鼠标右鍵 4920819 如何实现屏幕截图 4920820 如何将截取的图片保存为指定图片格式 4930821 如何复制程序本身 4930822 分段<em>显示</em>电话号码颜色 4930823 软件版本号是如何组成的 4930824 单击“关闭”按钮或按+键时最小化窗口 4940825 屏蔽RichTextBox控件+快捷键 49518.4 其他 4950826 将DataGridView控件<em>中</em>的<em>数据</em>导入Excel 4950827 无法获取自定义环境变量的值 4960828 将组件放到COM+服务器上去 4960829 调用非托管的DLL文件 4970830 如何将GridView控件<em>数据</em>导入Word 4970831 如何将GridView控件<em>数据</em>导入Excel 4970832 单片机如何实现在线调试 4980833 单片机如何实现内存优化管理 4980834 单片机实现文件系统管理 4980835 杀死进程 4980836 如何下载某网站上的图片资源 498第19章 SQL查询相关技术 50119.1 常用SQL查询技术 5020837 如何在查询<em>中</em>正确使用单引号“’” 5020838 SQL<em>中</em>SELECT语句的执行顺序 5020839 在查询时查询<em>数据</em>为指定长度的<em>数据</em> 5020840 如何利用WHERE参数过滤<em>数据</em> 5030841 如何正确地理解和运用SQL<em>中</em>的判式 5030842 如何正确地理解和使用SQL<em>中</em>的关键字 50319.2 比较、逻辑运算符查询 5040843 如何使用算术运算符号进行比较查询 5040844 如何使用比较运算符号进行比较查询 5040845 如何使用AND逻辑运算符查询 5050846 如何使用OR逻辑运算符查询 5060847 如何联合使用AND和OR运算符查询 5060848 如何在查询<em>中</em>正确使用逻辑操作符 5070849 利用通配符进行查询 50719.3 SQL关键字查询 5080850 如何使用ESCAPE关键字规定转义字符 5080851 如何使用BETWEEN进行范围查询 5080852 如何使用NOT BETWEEN进行范围查询 5090853 如何使用GROUP BY子句查询 5090854 如何使用HAVING语句过滤分组<em>数据</em> 5100855 如何使用ALL关键字查询 5100856 如何使用CUBE关键字查询 51119.4 表结构与性能 5110857 检测信息是否存在 5110858 @@CPU_BUSY获取CPU的工作时间 5110859 如何获取磁盘读写次数 5120860 获取SQL Server服务器名 5120861 获取<em>数据</em>库标识号 5120862 判断用户是否访问<em>数据</em>的权限 5120863 <em>显示</em>表<em>中</em>列信息 5120864 <em>显示</em>表<em>中</em>任意列名称 5130865 提高SQL性能加快执行速度 5130866 控制批处理内语句的执行 5130867 执行查询但是<em>显示</em>列信息 5140868 获取连接或试图连接的次数 5140869 获取当前<em>数据</em>库的语言名 51419.5 时间与谓词 5140870 时间函数的使用 5140871 设置<em>数据</em>库时间表显形式 5150872 格式化日期<em>显示</em>格式 5150873 如何正确理解SQL<em>中</em>的NULL值 5160874 如何使用IsNull()函数来处理空值 5160875 如何使用Nullif()函数来处理空值 5160876 查询空值(NULL)的技巧 5170877 利用关键字DISTINCT去除重复记录 5170878 巧用TOP子句获取信息 5180879 巧用CONTAINS谓词检索信息 5180880 通过ISNULL替换信息 5190881 比较COMPUTE和GROUP BY 5190882 如何对指定时间段进行查询 5190883 对某期间的<em>数据</em>进行查询的几种方法 5190884 NOT与谓词进行组合条件的查询 52019.6 聚合函数 5200885 聚合函数SUM的使用 5200886 聚合函数AVG的使用 5210887 如何使用聚合函数MAX 5210888 如何使用聚合函数MIN 5220889 如何使用聚合函数COUNT 5220890 如何使用聚合函数First或Last 52319.7 子查询与连接查询 5230891 union与连接之间的区别 5230892 如何应用IN查询表<em>中</em>的记录信息 5240893 使用一个单行的子查询来更新列 5240894 使用IN引入子查询限定查询范围 5240895 在UPDATE语句<em>中</em>应用子查询 5250896 如何应用子查询 5250897 EXISTS与子查询联合应用 5250898 在FROM子句<em>中</em>的子查询 5250899 在DELETE语句<em>中</em>应用子查询 5260900 子查询与聚合函数的应用 5260901 有效使用内连接 5260902 如何使用LEFT OUTER JOIN查询 5260903 如何使用RIGHT OUTER JOIN查询 5270904 利用CASE语句查询结果 52719.8 交叉表 5280905 Access<em>中</em>利用TRASFORM分析<em>数据</em> 5280906 Access<em>中</em>利用TRASFORM动态分析<em>数据</em> 5290907 SQL Server实现静态交叉表 5290908 SQL Server实现动态交叉表 53119.9 常用<em>数据</em>操作 5320909 如何对字符串进行查询 5320910 如何进行单条<em>数据</em>的添加 5330911 如何进行批量<em>数据</em>的添加 5330912 如何对<em>数据</em>进行修改 5340913 如何对<em>数据</em>进行删除 5340914 对<em>数据</em>库<em>数据</em>进行局部删除 53419.10 高级应用 5350915 如何使用临时表 5350916 如何查询表<em>中</em>的列名 5350917 在查询<em>中</em>如何防止输入指定符串 5360918 查询指定长度的<em>数据</em> 5360919 获取当前<em>数据</em>库的详细信息 5370920 在查询过程<em>中</em>灵活定义与使用别名 53819.11 视图、存储过程和触发器的使用 5380921 如何正确认识视图 5380922 如何获取<em>数据</em>库<em>中</em>的全部用户视图 5390923 如何通过视图修改<em>数据</em> 5390924 如何正确理解存储过程 5400925 如何获取<em>数据</em>库<em>中</em>的全部存储过程 5400926 如何正确认识触发器 5410927 Update触发器在系统日志<em>中</em>的应用 5420928 触发器的嵌套使用 5420929 获取<em>数据</em>库<em>中</em>的触发器 54319.12 其他 5440930 在查询程序<em>中</em>使用变量 5440931 对查询结果进行排序 5440932 批量获取结果集信息 5450933 对查询结果生成表 5450934 实现<em>数据</em>类型转换 5460935 获取当前<em>数据</em>库的登录用户名 5460936 如何正确理解<em>数据</em>库键字 5460937 将结果转换为XML形式 5470938 追加查询结果到已存在的表 5470939 利用对多个表<em>中</em>的字段创建新记录集 5470940 利用EXECUTE执行SQL语句 548第20章 <em>数据</em>库技术 54920.1 Access<em>数据</em>库的使用 5500941 如何为Access<em>数据</em>库设置密码 5500942 如何创建加密的Access<em>数据</em>库 5500943 建立Access<em>数据</em>库连接 5510944 与加密后的Access<em>数据</em>库建立连接 5510945 如何提取Access<em>数据</em>库<em>中</em>的<em>数据</em>表名 5510946 随机读取Access<em>数据</em>库记录 5520947 将Access<em>数据</em>库导入到Excel<em>中</em>(ASP.NET) 5520948 在.NET 2.0框架下动态创建Access<em>数据</em>库 5530949 在.NET 2.0框架下动态创建Access<em>数据</em>表 5530950 如何备份Access<em>数据</em>库 55420.2 SQL<em>数据</em>库的使用 5540951 建立SQL Server<em>数据</em>库连接 5540952 如何使用ODBC访问SQL Server<em>数据</em>库 5550953 读取SQL Server<em>数据</em>表结构 5560954 在C#<em>中</em>分离SQL Server<em>数据</em>库 5570955 C#<em>中</em>附加SQL Server<em>数据</em>库 5580956 C#<em>中</em>附加单文件SQL Server<em>数据</em>库 5590957 备份SQL Server<em>数据</em>库 5590958 还原SQL Server<em>数据</em>库 5600959 开启SQL Server<em>数据</em>库服务 5610960 断开SQL Server<em>数据</em>库服务 5620961 如何判断SQL Server<em>数据</em>库连接状态 5620962 获取连接SQL Server<em>数据</em>库的名称 5630963 获取SQL Server的连接统计<em>数据</em> 5630964 如何调用SQL Server存储过程 5630965 如何生成SQL<em>数据</em>库脚本 5640966 SQL Server 2000无法安装的解决办法 56520.3 其他 5650967 如何判断记录是否为NULL 5650968 建立Oracle<em>数据</em>库连接 5660969 如何在<em>数据</em>表<em>中</em>设置主键 5660970 DataSet读取XML文件<em>中</em><em>数据</em>作为<em>数据</em>源 5670971 如何读取Fox的DBF文件 5670972 通用方法实现<em>数据</em>增、删、改功能 5670973 通用方法获取查询结果DataSet<em>数据</em>集 5680974 同时查询多条SQL语句 5680975 如何判断是否查询到结果 5680976 将图片以二进制格式存储到<em>数据</em>库<em>中</em>(asp.net) 5690977 从DataReader对象读取<em>数据</em>的技巧 5690978 随机<em>显示</em><em>数据</em>库记录 5690979 通过DataTable获得<em>数据</em>表的主键 5690980 将Access<em>数据</em>库转化为SQL Server<em>数据</em>库 5700981 将SQL Server<em>数据</em>库转化为Access<em>数据</em>库 5710982 如何避免<em>数据</em>库死锁现象 5720983 如何调用带输入参数的存储过程 5720984 如何获取存储过程返回的结果集 5730985 取得<em>数据</em>表某个单元格的值 5730986 在ASP.NET2.0下将<em>数据</em>绑定DropDownList 5730987 在ADO.NET<em>中</em>实现<em>数据</em>库的事务处理 5740988 将任意文件保存到<em>数据</em>库<em>中</em> 5740989 将存储在<em>数据</em>库<em>中</em>的文件提取出来 5750990 合并具有相同<em>数据</em>表结构的查询结果 5750991 使用DataTable进行<em>数据</em>检索 5750992 使用DataView对<em>数据</em>进行检索和排序 5760993 使用DataSet建立DataTable明细表 576第21章 打印与报表技术 57921.1 报表设计技术 5800994 如何快速创建水晶报表 5800995 如何编写带图片的报表 5820996 如何使图片成为整个报表的背景 5830997 如何设置水晶报表<em>中</em>节的背景图片 5830998 如何设置水晶报表<em>中</em>节的背景色 5840999 如何设置水晶报表的页面 5841000 如何在报表<em>中</em>添加节 5841001 如何在报表<em>中</em>移动节的顺序 5851002 如何在报表<em>中</em>合并节 5851003 如何在报表<em>中</em>册除节 5851004 如何在报表<em>中</em><em>显示</em>与隐藏节 5861005 如何设置多列样式报表 5861006 如何设置报表<em>中</em>节的高度 5871007 如何设置报表的摘要信息 5871008 如何设置报表的打印日期与时间 58721.2 报表格式化类对象技巧 5881009 如何在报表<em>中</em>使用文本对象 5881010 如何移动对象操作 5881011 如何对齐多个对象 5891012 如何使用公式字段 5891013 如何在报表<em>中</em>使用线 5901014 如何在报表<em>中</em>使用方框 59021.3 报表<em>数据</em>排序与分组技巧 5911015 如何排序报表<em>数据</em> 5911016 如何报表<em>数据</em>分组 5911017 如何报表<em>中</em>筛选<em>数据</em> 5921018 如何对分组报表<em>中</em>的页码进行设置 59221.4 报表的应用技巧 5931019 如何在水晶报表<em>中</em>使用交叉表 5931020 如何在水晶报表<em>中</em>使用子报表 5941021 如何动态<em>显示</em>子报表 5961022 如何删除子报表 5971023 如何在报表<em>中</em>计算百分比 59721.5 Windows打印控件应用技巧 5991024 如何使用PrintDocument控件打印窗体<em>数据</em> 5991025 如何使用PrintPreviewContronl控件预览 5991026 使用PrintPreviewDialog对话框 6001027 如何使用PrintDialog对话框打印 6011028 如何使用PageSetupDialog对话框设置页面 6011029 如何使用PrintDocument控件打印文本文件 602第22章 C#高级应用开发 60522.1 线程的使用 6061030 如何开始一个线程 6061031 如何结束一个线程 6061032 如何使线程休眠 6061033 如何挂起一个线程 6061034 如何判断线程的状态 6061035 如何实现线程的同步 6071036 如何避免死锁 60722.2 .NET 2.0的新特性 6071037 如何使用泛型 6071038 如何使用匿名方法 6081039 如何使用迭代器 6091040 如何使用分部类 61022.3 C#<em>Web</em>Service 6101041 建立SQL Server返回<em>数据</em>集<em>Web</em>Service 6101042 利用<em>Web</em>Service传送图片 61122.4 文件监视 6111043 如何监视文件的创建 6111044 如何监视文件的改变 6121045 如何监视文件的重命名 6121046 如何监视文件的删除 61322.5 C#高级应用 6131047 如何将聊天程序做成Windows服务 6131048 COM+服务解决同时访问大量<em>数据</em>并发性 6151049 COM+服务实现银行转账系统 6171050 如何用Remoting技术传送文件 6191051 大规模<em>数据</em>访问时缓解服务器压力 620第23章 硬件及相关开发技术 62323.1 语音卡、IC卡、神龙卡的使用 6241052 利用语音卡拨</a></div><div data-report-view="{"mod":"popu_645","index":"4","dest":"https://download.csdn.net/download/yxbbbs283127372/3325262","strategy":"2~default~OPENSEARCH~Rate","extra":"{\"utm_medium\":\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-4-3325262-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\",\"dist_request_id\":\"1713920331325_95453\"}","spm":"1035.2023.3001.6557"}" class="list-item" data-v-ca2d15ac><div class="recommend-title" data-v-ca2d15ac><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAltJREFUWEdjZGBgYGhv/yD45//nEEYGBrX//xj4QWK0AoxMDB//MzDcYmHkXVNZKfCeEWz5v8/1DP8ZuGhlKVZzGRm+sTDxNjI2tz1OZfjHYEpXy2GWMTGcZmxpe9xN62DH5TlQdDA2tzyeNSC+h1o66gCyQyApUdRNSIhNGBSS7979ejtv/utd5EQl2Q7IypT0ExJiFoc44O/LadOfbxp1wPAOAWlpdr5Pn//8/Pzp70+QT3GlAX5+ZnYeHhb2p09/fiImRIhOhBYWvIo21ryWu/Z8PHDp4tdn2BxgoM8l4+IiYH/k6OdjJ058vk91B7g487swMDD8v3Hj+2VJSTYpfn5mEZAlHz/9ffPq5e+Xqqoc2iD+nr0f99DSAQQ9RhMHcHAwsYSGCtvKy7Gr4HPBo0c/b69c/fbwzx///hJ0KQMDA9FpAGaYizO/tpkZjwUTEyMTsgX//v3/d/LUl+N79368RozFMDUkOwCkUUODU8zHW9CFg4OJG8T/8ePf181b3u25efPHK1IsB6nF6gAjY25ZEWFWcNPs169/fw4c+HQD3WBBIRaOsBAhZ5D4qjXv9r5/9+cHuhoHBz4NNjYmFpD4m7e/P547+/UxuhqsDoiPE3WWlWVXgvju/5ee3qfLsfmMiZmBEST+7y/Df2zyJcXSkRwcjDwgucePf95buOj1Xqo6gFBwDw8H/P/P8O/nz//fCPkWmzw7OyMXIyMDOLeQHQXkWIxNz9BygJubgI6kBCu4tUMt8PzF75e7dn24QlQuoJalxJgzCDomA901G/DOKSieBrJ7DgCPdYFAskV/NwAAAABJRU5ErkJggg==" alt data-v-ca2d15ac> <a target="_blank" href="https://download.csdn.net/download/yxbbbs283127372/3325262" data-report-click="{"mod":"popu_645","index":"4","dest":"https://download.csdn.net/download/yxbbbs283127372/3325262","strategy":"2~default~OPENSEARCH~Rate","extra":"{\"utm_medium\":\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-4-3325262-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\",\"dist_request_id\":\"1713920331325_95453\"}","spm":"1035.2023.3001.6557"}" data-report-query="spm=1035.2023.3001.6557&utm_medium=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-4-3325262-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default&depth_1-utm_source=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-4-3325262-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default" class="title" data-v-ca2d15ac>二十三种设计模式【PDF版】</a></div> <a target="_blank" href="https://download.csdn.net/download/yxbbbs283127372/3325262" data-report-click="{"mod":"popu_645","index":"4","dest":"https://download.csdn.net/download/yxbbbs283127372/3325262","strategy":"2~default~OPENSEARCH~Rate","extra":"{\"utm_medium\":\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-4-3325262-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\",\"dist_request_id\":\"1713920331325_95453\"}","spm":"1035.2023.3001.6557"}" data-report-query="spm=1035.2023.3001.6557&utm_medium=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-4-3325262-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default&depth_1-utm_source=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-4-3325262-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default" class="desc" data-v-ca2d15ac>主要是介绍各种格式流行的软件设计模式,对于程序员的进一步提升起推进作用,有时间可以随便翻翻~~ 23种设计模式汇集 如果你还不了解设计模式是什么的话? 那就先看设计模式引言 ! 学习 GoF 设计模式的重要性 建筑和软件<em>中</em>模式之异同 A. 创建模式 设计模式之 Singleton(单态/单件) 阎宏博士讲解:单例(Singleton)模式 保证一个类只有一个实例,并提供一个访问它的全局访问点 设计模式之 Factory(工厂方法和抽象工厂) 使用工厂模式就象使用 new 一样频繁. 设计模式之 Builder 汽车由车轮 方向盘 发动机很多部件组成,同时,将这些部件组装成汽车也是一件复杂的工作,Builder 模式就是将这两 种情况分开进行。 设计模式之 Prototype(原型) 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 B. 结构模式 设计模式之 Adapter(适配器) 使用类再生的两个方式:组合(new)和继承(extends),这个已经在 thinking in java<em>中</em>提到过. 设计模式之 Proxy(代理) 以 Jive 为例,剖析代理模式在用户级别授权机制上的应用 设计模式之 Facade(门面?) 可扩展的使用 JDBC针对不同的<em>数据</em>库编程,Facade提供了一种灵活的实现. 设计模式之 Composite(组合) 就是将类用<em>树形</em>结构组合成一个单位.你向别人介绍你是某单位,你是单位<em>中</em>的一个元素,别人和你做买卖,相当于 和单位做买卖。文章<em>中</em>还对 Jive再进行了剖析。 设计模式之 Decorator(装饰器) Decorator 是个油漆工,给你的东东的外表刷上美丽的颜色. 设计模式之 Bridge(桥连) 将牛郎织女分开(本应在一起,分开他们,形成两个接口),在他们之间搭建一个桥(动态的结合) 设计模式之 Flyweight(共享元) 提供 Java运行性能,降低小而大量重复的类的开销. C. 行为模式 设计模式之 Command(命令) 什么是将行为封装,Command 是最好的说明. 设计模式之 Observer(观察者) 介绍如何使用 Java API 提供的现成 Observer 设计模式之 Iterator(迭代器) 这个模式已经被整合入Java的Collection.在大多数场合下无需自己制造一个Iterator,只要将对象装入Collection<em>中</em>, 直接使用 Iterator 进行对象遍历。 设计模式之 Template(模板方法) 实际上向你介绍了为什么要使用 Java 抽象类,该模式原理简单,使用很普遍. 设计模式之 Strategy(策略) 不同算法各自封装,用户端可随意挑选需要的算法. 设计模式之 Chain of Responsibility(责任链) 各司其职的类串成一串,好象击鼓传花,当然如果自己能完成,就不要推委给下一个. 设计模式之 Mediator(<em>中</em>介) Mediator 很象十字路口的红绿灯,每个车辆只需和红绿灯交互就可以. 设计模式之 State(状态) 状态是编程<em>中</em>经常碰到的实例,将状态对象化,设立状态变换器,便可在状态<em>中</em>轻松切换. 设计模式之 Memento(注释状态?) 很简单一个模式,就是在内存<em>中</em>保留原来<em>数据</em>的拷贝. 设计模式之 Interpreter(解释器) 主要用来对语言的分析,应用机会不多. 设计模式之 Visitor(访问者) 访问者在进行访问时,完成一系列实质性操作,而且还可以扩展. 设计模式引言 设计面向对象软件比较困难,而设计可复用的面向对象软件就更加困难。你必须找到相关的对象,以适当的粒度将它们归 类,再定义类的接口和继承层次,建立对象之间的基本关系。你的设计应该对手头的问题有针对性,同时对将来的问题和需求 也要有足够的通用性。 你也希望避免重复设计或尽可能少做重复设计。有经验的面向对象设计者会告诉你,要一下子就得到复用性和灵活性好的设计, 即使不是不可能的至少也是非常困难的。一个设计在最终完成之前常要被复用好几次,而且每一次都有所修改。 有经验的面向对象设计者的确能做出良好的设计,而新手则面对众多选择无从下手,总是求助于以前使用过的非面向对象 技术。新手需要花费较长时间领会良好的面向对象设计是怎么回事。有经验的设计者显然知道一些新手所不知道的东西,这又 是什么呢? 内行的设计者知道:不是解决任何问题都要从头做起。他们更愿意复用以前使用过的解决方案。当找到一个好的解决方案,他 们会一遍又一遍地使用。这些经验是他们成为内行的部分原因。因此,你会在许多面向对象系统<em>中</em>看到类和相互通信的对象( c o m m u n i c a t i n go b j e c t)的重复模式。这些模式解决特定的设计问题,使面向对象设计更灵活、优雅,最终复用性更 好。它们帮助设计者将新的设计建立在以往工作的基础上,复用以往成功的设计方案。 一个熟悉这些模式的设计者不需要再去发现它们,而能够立即将它们应用于设计问题<em>中</em>。以下类比可以帮助说明这一点。 小说家和剧本作家很少从头开始设计剧情。他们总是沿袭一些业已存在的模式,像“悲剧性英雄”模式(《麦克白》、《哈姆雷特》 等)或“浪漫小说”模式(存在着无数浪漫小说)。同样地,面向对象设计员也沿袭一些模式,像“用对象表示状态”和“修饰对象以便 于你能容易地添加/删除属性”等。一旦懂得了模式,许多设计决策自然而然就产生了。 我们都知道设计经验的重要价值。你曾经多少次有过这种感觉—你已经解决过了一个问题但就是不能确切知道是在什么地 方或怎么解决的?如果你能记起以前问题的细节和怎么解决它的,你就可以复用以前的经验而不需要重新发现它。然而,我们 并没有很好记录下可供他人使用的软件设计经验。 学习 GoF设计模式的重要性 著名的 EJB 领域顶尖的专家 Richard Monson-Haefel 在其个人网站:www.EJBNow.com <em>中</em>极力推荐的 GoF 的《设计模式》,原文 如下: Design Patterns Most developers claim to experience an epiphany reading this book. If you've never read the Design Patterns book then you have suffered a very serious gap in your programming education that should be remedied immediately. 翻译: 很多程序员在读完这本书,宣布自己相当于经历了一次"主显节"(纪念那稣降生和受洗的双重节日),如果你从来没有读 过这本书,你会在你的程序教育生涯里存在一个严重裂沟,所以你应该立即挽救弥补! 可以这么说:GoF 设计模式是程序员真正掌握面向对象核心思想的必修课。虽然你可能已经通过了 SUN 的很多令人炫目的 技术认证,但是如果你没有学习掌握 GoF 设计模式,只能说明你还是一个技工。 在浏览《Thingking in Java》(第一版)时,你是不是觉得好象这还是一本 Java 基础语言书籍?但又不纯粹是,因为这本书的作 者将面向对象的思想巧妙的融合在 Java 的具体技术上,潜移默化的让你感觉到了一种新的语言和新的思想方式的诞生。 但是读完这本书,你对书<em>中</em>这些蕴含的思想也许需要一种更明晰更系统更透彻的了解和掌握,那么你就需要研读 GoF 的《设 计模式》了。 《Thingking in Java》(第一版<em>中</em>文)是这样描述设计模式的:他在由 Gamma, Helm 和 Johnson Vlissides 简称 Gang of Four(四人 帮),缩写 GoF 编著的《Design Patterns》一书<em>中</em>被定义成一个“里程碑”。事实上,那本书现在已成为几乎所有 OOP(面向对象程 序设计)程序员都必备的参考书。(在国外是如此)。 GoF 的《设计模式》是所有面向对象语言(C++ Java C#)的基础,只不过不同的语言将之实现得更方便地使用。 GOF 的设计模式是一座"桥" 就 Java 语言体系来说,GOF 的设计模式是 Java 基础知识和 J2EE 框架知识之间一座隐性的"桥"。 会 Java 的人越来越多,但是一直徘徊在语言层次的程序员不在少数,真正掌握 Java <em>中</em>接口或抽象类的应用不是很多,大家 经常以那些技术只适合大型项目为由,避开或忽略它们,实际<em>中</em>,Java 的接口或抽象类是真正体现 Java 思想的核心所在,这些 你都将在 GoF 的设计模式里领略到它们变幻无穷的魔力。 GoF 的设计模式表面上好象也是一种具体的"技术",而且新的设计模式不断在出现,设计模式自有其自己的发展轨道,而这 些好象和 J2EE .Net 等技术也无关! 实际上,GoF 的设计模式并不是一种具体"技术",它讲述的是思想,它不仅仅展示了接口或抽象类在实际案例<em>中</em>的灵活应用 和智慧,让你能够真正掌握接口或抽象类的应用,从而在原来的 Java 语言基础上跃进一步,更重要的是,GoF 的设计模式反复 向你强调一个宗旨:要让你的程序尽可能的可重用。 这其实在向一个极限挑战:软件需求变幻无穷,计划没有变化快,但是我们还是要寻找出不变的东西,并将它和变化的东 西分离开来,这需要非常的智慧和经验。 而 GoF 的设计模式是在这方面开始探索的一块里程碑。 J2EE 等属于一种框架软件,什么是框架软件?它不同于我们以前接触的 Java API 等,那些属于 Toolkist(工具箱),它不再被动 的被使用,被调用,而是深刻的介入到一个领域<em>中</em>去,J2EE 等框架软件设计的目的是将一个领域<em>中</em>不变的东西先定义好,比如 整体结构和一些主要职责(如<em>数据</em>库操作 事务跟踪 安全等),剩余的就是变化的东西,针对这个领域<em>中</em>具体应用产生的具体不同 的变化需求,而这些变化东西就是 J2EE 程序员所要做的。 由此可见,设计模式和 J2EE 在思想和动机上是一脉相承,只不过 1.设计模式更抽象,J2EE 是具体的产品代码,我们可以接触到,而设计模式在对每个应用时才会产生具体代码。 2.设计模式是比 J2EE 等框架软件更小的体系结构,J2EE <em>中</em>许多具体程序都是应用设计模式来完成的,当你深入到 J2EE 的内 部代码研究时,这点尤其明显,因此,如果你不具备设计模式的基础知识(GoF 的设计模式),你很难快速的理解 J2EE。不能理解 J2EE,如何能灵活应用? 3.J2EE 只是适合企业计算应用的框架软件,但是 GoF 的设计模式几乎可以用于任何应用!因此 GoF 的设计模式应该是 J2EE 的重要理论基础之一。 所以说,GoF 的设计模式是 Java 基础知识和 J2EE 框架知识之间一座隐性的"桥"。为什么说隐性的? GOF 的设计模式是一座隐性的"桥" 因为很多人没有注意到这点,学完 Java 基础语言就直接去学 J2EE,有的甚至鸭子赶架,直接使用起 <em>Web</em>logic 等具体 J2EE 软 件,一段时间下来,发现不过如此,挺简单好用,但是你真正理解 J2EE 了吗?你在具体案例<em>中</em>的应用是否也是在延伸 J2EE 的思 想? 如果你不能很好的延伸 J2EE 的思想,那你岂非是大炮轰蚊子,认识到 J2EE 不是适合所有场合的人至少是明智的,但我们更 需要将 J2EE 用对地方,那么只有理解 J2EE 此类框架软件的精髓,那么你才能真正灵活应用 Java 解决你的问题,甚至构架出你自 己企业的框架来。(我们不能总是使用别人设定好的框架,为什么不能有我们自己的框架?) 因此,首先你必须掌握 GoF 的设计模式。虽然它是隐性,但不是可以越过的。 关于本站“设计模式” Java 提供了丰富的 API,同时又有强大的<em>数据</em>库系统作底层支持,那么我们的编程似乎变成了类似积木的简单"拼凑"和调用, 甚至有人提倡"蓝领程序员",这些都是对现代编程技术的不了解所至. 在真正可复用的面向对象编程<em>中</em>,GoF 的《设计模式》为我们提供了一套可复用的面向对象技术,再配合 Refactoring(重构方法), 所以很少存在简单重复的工作,加上Java 代码的精炼性和面向对象纯洁性(设计模式是 java 的灵魂),编程工作将变成一个让你时刻 体验创造快感的激动人心的过程. 为能和大家能共同探讨"设计模式",我将自己在学习<em>中</em>的心得写下来,只是想帮助更多人更容易理解 GoF 的《设计模式》。由 于原著都是以C++为例, 以Java为例的设计模式基本又都以图形应用为例,而我们更关心Java在<em>中</em>间件等服务器方面的应用,因此, 本站所有实例都是非图形应用,并且顺带剖析 Jive论坛系统.同时为降低理解难度,尽量避免使用 UML 图. 如果你有一定的面向对象编程经验,你会发现其<em>中</em>某些设计模式你已经无意识的使用过了;如果你是一个新手,那么从开始就 培养自己良好的编程习惯(让你的的程序使用通用的模式,便于他人理解;让你自己减少重复性的编程工作),这无疑是成为一个优秀 程序员的必备条件. 整个设计模式贯穿一个原理:面对接口编程,而不是面对实现.目标原则是:降低耦合,增强灵活性. 建筑和软件<em>中</em>模式之异同 CSDN 的透明特别推崇《建筑的永恒之道》,认为从<em>中</em>探寻到软件的永恒之道,并就"设计模式"写了专门文章《探寻软件的永恒 之道 》,其<em>中</em>很多观点我看了很受启发,以前我也将"设计模式" 看成一个简单的解决方案,没有从一种高度来看待"设计模式"在软 件<em>中</em>地位,下面是我自己的一些想法: 建筑和软件某些地方是可以来比喻的 特别是<em>中</em>国传统建筑,那是很讲模式的,这些都是传统文化使然,比如京剧 一招一式都有套路;<em>中</em>国画,也有套路,树应该怎么画 法?有几种画法?艺术大家通常是创造出自己的套路,比如明末清初,水墨画法开始成熟,这时画树就不用勾勒这个模式了,而是一笔 下去,浓淡几个叶子,待毛笔的水墨要干枯时,画一下树干,这样,一个活生写意的树就画出来. 我上面这些描述其实都是一种模式,创建模式的人是大师,但是拘泥于模式的人永远是工匠. 再回到传统建筑<em>中</em>,<em>中</em>国的传统建筑是过分注重模式了,所以建筑风格发展不大,基本分南北两派,大家有个感觉,旅游时,到南 方,你发现古代名居建筑都差不多;北方由于受满人等少数民族的影响,在建筑色彩上有些与南方迥异,但是很多细节地方都差不多. 这些都是模式的体现. 由于建筑受材料和功用以及费用的影响,所用模式种类不多,这点是和软件很大的不同. 正因为这点不同,导致建筑的管理模式和软件的管理模式就有很多不同, 有些人认识不到这点,就产生了可以大量使用"软件 蓝领"的想法,因为他羡慕建筑<em>中</em>"民工"的低成本. 要知道软件还有一个与建筑截然相反的责任和用途,那就是:现代社会<em>中</em>,计划感不上变化,竞争激烈,所有一切变幻莫测,要应 付所有这些变化,首推信息技术<em>中</em>的软件,只有软件能够帮助人类去应付各种变化.而这点正好与建筑想反,建筑是不能帮助人类去 应付变化的,(它自己反而要求稳固,老老实实帮助人遮风避雨,总不能叫人类在露天或树叶下打开电脑编软件吧). 软件要帮助人类去应付变化,这是软件的首要责任,所以,软件<em>中</em>模式产生的目的就和建筑不一样了,建筑<em>中</em>的模式产生可以因 为很多原因:建筑大师的创意;材料的革新等;建筑<em>中</em>这些模式一旦产生,容易发生另外一个缺点,就是有时会阻碍建筑本身的发展, 因为很多人会不思创造,反复使用老的模式进行设计,阻碍建筑的发展. 但是在软件<em>中</em>,这点正好相反,软件模式的产生是因为变化的东西太多,为减轻人类的负担,将一些不变的东西先用模式固化,这 样让人类可以更加集<em>中</em>精力对付变化的东西,所以在软件<em>中</em>大量反复使用模式(我个人认为这样的软件就叫框架软件了,比如J2EE), 不但没阻碍软件的发展,反而是推动了软件的发展.因为其他使用这套软件的人就可以将更多精力集<em>中</em>在对付那些无法用模式的 应用上来. 可以关于建筑和软件<em>中</em>的模式作用可以总结如下: 在软件<em>中</em>,模式是帮助人类向"变化"战斗,但是在软件<em>中</em>还需要和'变化'直接面对面战斗的武器:人的思维,特别是创造 分析思 维等等,这些是软件真正的灵魂,这种思维可以说只要有实践需求(如有新项目)就要求发生,发生频度高,人类的创造或分析思 维决定了软件的质量和特点。 而在建筑<em>中</em>,模式可以构成建筑全部知识,当有新的需求(如有新项目),一般使用旧的模式都可以完成,因此对人类的创造以 及分析思维不是每个项目都必须的,也不是非常重要的,对创造性的思维的需求只是属于锦上添花(除非人类以后离开地球居 住了〕。 设计模式之 Singleton(单态) 模式实战书籍《Java实用系统开发指南》 单态定义: Singleton 模式主要作用是保证在 Java 应用程序<em>中</em>,一个类 Class 只有一个实例存在。 在很多操作<em>中</em>,比如建立目录 <em>数据</em>库连接都需要这样的单线程操作。 还有, singleton 能够被状态化; 这样,多个单态类在一起就可以作为一个状态仓库一样向外提供服务,比如,你要论坛<em>中</em>的 帖子计数器,每次浏览一次需要计数,单态类能否保持住这个计数,并且能 synchronize 的安全自动加 1,如果你要把这个数字 永久保存到<em>数据</em>库,你可以在不修改单态接口的情况下方便的做到。 另外方面,Singleton 也能够被无状态化。提供工具性质的功能, Singleton 模式就为我们提供了这样实现的可能。使用 Singleton 的好处还在于可以节省内存,因为它限制了实例的个数,有 利于 Java 垃圾回收(garbage collection)。 我们常常看到工厂模式<em>中</em>类装入器(class loader)<em>中</em>也用 Singleton 模式实现的,因为被装入的类实际也属于资源。 如何使用? 一般 Singleton 模式通常有几种形式: public class Singleton { private Singleton(){} //在自己内部定义自己一个实例,是不是很奇怪? //注意这是 private 只供内部调用 private static Singleton instance = new Singleton(); //这里提供了一个供外部访问本 class 的静态方法,可以直接访问 public static Singleton getInstance() { return instance; } } 第二种形式: public class Singleton { private static Singleton instance = null; public static synchronized Singleton getInstance() { //这个方法比上面有所改进,不用每次都进行生成对象,只是第一次 //使用时生成实例,提高了效率! if (instance==null) instance=new Singleton(); return instance; } } 使用 Singleton.getInstance()可以访问单态类。 上面第二<em>中</em>形式是 lazy initialization,也就是说第一次调用时初始 Singleton,以后就不用再生成了。 注意到 lazy initialization 形式<em>中</em>的 synchronized,这个 synchronized 很重要,如果没有 synchronized,那么使用 getInstance() 是有可能得到多个 Singleton 实例。关于 lazy initialization 的 Singleton 有很多涉及 double-checked locking (DCL)的讨论,有兴趣者 进一步研究。 一般认为第一种形式要更加安全些。 使用 Singleton 注意事项: 有时在某些情况下,使用 Singleton 并不能达到 Singleton 的目的,如有多个 Singleton 对象同时被不同的类装入器装载;在 EJB 这样的分布式系统<em>中</em>使用也要注意这种情况,因为 EJB 是跨服务器,跨 JVM 的。 我们以 SUN 公司的宠物店源码(Pet Store 1.3.1)的 ServiceLocator 为例稍微分析一下: 在 Pet Store<em>中</em> ServiceLocator 有两种,一个是 EJB 目录下;一个是 <em>WEB</em> 目录下,我们检查这两个 ServiceLocator 会发现内容 差不多,都是提供 EJB 的查询定位服务,可是为什么要分开呢?仔细研究对这两种 ServiceLocator 才发现区别:在 <em>WEB</em> <em>中</em>的 ServiceLocator 的采取 Singleton 模式,ServiceLocator 属于资源定位,理所当然应该使用 Singleton 模式。但是在 EJB <em>中</em>,Singleton 模式已经失去作用,所以 ServiceLocator 才分成两种,一种面向 <em>WEB</em> 服务的,一种是面向 EJB 服务的。 Singleton 模式看起来简单,使用方法也很方便,但是真正用好,是非常不容易,需要对 Java 的类 线程 内存等概念有相当 的了解。 总之:如果你的应用基于容器,那么 Singleton 模式少用或者不用,可以使用相关替代技术。 进一步深入可参考: Double-checked locking and the Singleton pattern When is a singleton not a singleton? 设计模式如何在具体项目<em>中</em>应用见《Java 实用系统开发指南》。 设计模式之 Factory 工厂模式定义:提供创建对象的接口. 为何使用? 工厂模式是我们最常用的模式了,著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。 为什么工厂模式是如此常用?因为工厂模式就相当于创建实例对象的 new,我们经常要根据类 Class 生成实例对象,如 A a=new A() 工厂模式也是用来创建实例对象的,所以以后 new时就要多个心眼,是否可以考虑实用工厂模式,虽然这样做, 可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。 我们以类 Sample为例, 如果我们要创建 Sample的实例对象: Sample sample=new Sample(); 可是,实际情况是,通常我们都要在创建 sample实例时做点初始化的工作,比如赋值 查询<em>数据</em>库等。 首先,我们想到的是,可以使用 Sample的构造函数,这样生成实例就写成: Sample sample=new Sample(参数); 但是,如果创建 sample 实例时所做的初始化工作不是象赋值这样简单的事,可能是很长一段代码,如果也写入构造函数 <em>中</em>,那你的代码很难看了(就需要 Refactor 重整)。 为什么说代码很难看,初学者可能没有这种感觉,我们分析如下,初始化工作如果是很长一段代码,说明要做的工作很多, 将很多工作装入一个方法<em>中</em>,相当于将很多鸡蛋放在一个篮子里,是很危险的,这也是有背于 Java 面向对象的原则,面向对象 的封装(Encapsulation)和分派(Delegation)告诉我们,尽量将长的代码分派“切割”成每段,将每段再“封装”起来(减少段和段 之间偶合联系性),这样,就会将风险分散,以后如果需要修改,只要更改每段,不会再发生牵一动百的事情。 在本例<em>中</em>,首先,我们需要将创建实例的工作与使用实例的工作分开, 也就是说,让创建实例所需要的大量初始化工作从 Sample的构造函数<em>中</em>分离出去。 这时我们就需要 Factory 工厂模式来生成对象了,不能再用上面简单 new Sample(参数)。还有,如果 Sample 有个继承 如 MySample, 按照面向接口编程,我们需要将 Sample 抽象成一个接口.现在 Sample 是接口,有两个子类 MySample 和 HisSample .我们要实例化他们时,如下: Sample mysample=new MySample(); Sample hissample=new HisSample(); 随着项目的深入,Sample可能还会"生出很多儿子出来", 那么我们要对这些儿子一个个实例化,更糟糕的是,可能还要对以 前的代码进行修改:加入后来生出儿子的实例.这在传统程序<em>中</em>是无法避免的. 但如果你一开始就有意识使用了工厂模式,这些麻烦就没有了. 工厂方法 你会建立一个专门生产 Sample实例的工厂: public class Factory{ public static Sample creator(int which){ //getClass 产生 Sample 一般可使用动态类装载装入类。 if (which==1) return new SampleA(); else if (which==2) return new SampleB(); } } 那么在你的程序<em>中</em>,如果要实例化 Sample 时.就使用 Sample sampleA=Factory.creator(1); 这样,在整个就不涉及到 Sample 的具体子类,达到封装效果,也就减少错误修改的机会,这个原理可以用很通俗的话来比喻: 就是具体事情做得越多,越容易范错误.这每个做过具体工作的人都深有体会,相反,官做得越高,说出的话越抽象越笼统,范错误可 能性就越少.好象我们从编程序<em>中</em>也能悟出人生道理?呵呵. 使用工厂方法 要注意几个角色,首先你要定义产品接口,如上面的 Sample,产品接口下有 Sample接口的实现类,如 SampleA,其次要有一个 factory 类,用来生成产品 Sample,如下图,最右边是生产的对象 Sample: 进一步稍微复杂一点,就是在工厂类上进行拓展,工厂类也有继承它的实现类 concreteFactory 了。 抽象工厂 工厂模式<em>中</em>有: 工厂方法(Factory Method) 抽象工厂(Abstract Factory). 这两个模式区别在于需要创建对象的复杂程度上。如果我们创建对象的方法变得复杂了,如上面工厂方法<em>中</em>是创建一个对象 Sample,如果我们还有新的产品接口 Sample2. 这里假设:Sample有两个 concrete 类 SampleA 和 SamleB,而 Sample2 也有两个 concrete类 Sample2A 和 SampleB2 那么,我们就将上例<em>中</em> Factory 变成抽象类,将共同部分封装在抽象类<em>中</em>,不同部分使用子类实现,下面就是将上例<em>中</em>的 Factory 拓展成抽象工厂: public abstract class Factory{ public abstract Sample creator(); public abstract Sample2 creator(String name); } public class SimpleFactory extends Factory{ public Sample creator(){ ......... return new SampleA } public Sample2 creator(String name){ ......... return new Sample2A } } public class BombFactory extends Factory{ public Sample creator(){ ...... return new SampleB } public Sample2 creator(String name){ ...... return new Sample2B } } 从上面看到两个工厂各自生产出一套 Sample和 Sample2,也许你会疑问,为什么我不可以使用两个工厂方法来分别生产 Sample和 Sample2? 抽象工厂还有另外一个关键要点,是因为 SimpleFactory 内,生产 Sample和生产 Sample2 的方法之间有一定联系, 所以才要将这两个方法捆绑在一个类<em>中</em>,这个工厂类有其本身特征,也许制造过程是统一的,比如:制造工艺比较简单,所以 名称叫 SimpleFactory。 在实际应用<em>中</em>,工厂方法用得比较多一些,而且是和动态类装入器组合在一起应用, 举例 我们以 Jive的 ForumFactory 为例,这个例子在前面的 Singleton 模式<em>中</em>我们讨论过,现在再讨论其工厂模式: public abstract class ForumFactory { private static Object initLock = new Object(); private static String className = "com.jivesoftware.forum.database.DbForumFactory"; private static ForumFactory factory = null; public static ForumFactory getInstance(Authorization authorization) { //If no valid authorization passed in, return null. if (authorization == null) { return null; } //以下使用了 Singleton 单态模式 if (factory == null) { synchronized(initLock) { if (factory == null) { ...... try { //动态转载类 Class c = Class.forName(className); factory = (ForumFactory)c.newInstance(); } catch (Exception e) { return null; } } } } //Now, 返回 proxy.用来限制授权对 forum 的访问 return new ForumFactoryProxy(authorization, factory, factory.getPermissions(authorization)); } //真正创建 forum 的方法由继承 forumfactory 的子类去完成. public abstract Forum createForum(String name, String description) throws UnauthorizedException, ForumAlreadyExistsException; .... } 因为现在的 Jive是通过<em>数据</em>库系统存放论坛帖子等内容<em>数据</em>,如果希望更改为通过文件系统实现,这个工厂方法 ForumFactory 就提供了提供动态接口: private static String className = "com.jivesoftware.forum.database.DbForumFactory"; 你可以使用自己开发的创建 forum 的方法代替 com.jivesoftware.forum.database.DbForumFactory 就可以. 在上面的一段代码<em>中</em>一共用了三种模式,除了工厂模式外,还有 Singleton 单态模式,以及 proxy模式,proxy 模式主要用来 授权用户对 forum 的访问,因为访问 forum 有两种人:一个是注册用户 一个是游客 guest,那么那么相应的权限就不一样,而且 这个权限是贯穿整个系统的,因此建立一个 proxy,类似网关的概念,可以很好的达到这个效果. 看看 Java 宠物店<em>中</em>的 CatalogDAOFactory: public class CatalogDAOFactory { /** * 本方法制定一个特别的子类来实现 DAO 模式。 * 具体子类定义是在 J2EE 的部署描述器<em>中</em>。 */ public static CatalogDAO getDAO() throws CatalogDAOSysException { CatalogDAO catDao = null; try { InitialContext ic = new InitialContext(); //动态装入 CATALOG_DAO_CLASS //可以定义自己的 CATALOG_DAO_CLASS,从而在无需变更太多代码 //的前提下,完成系统的巨大变更。 String className =(String) ic.lookup(JNDINames.CATALOG_DAO_CLASS); catDao = (CatalogDAO) Class.forName(className).newInstance(); } catch (NamingException ne) { throw new CatalogDAOSysException(" CatalogDAOFactory.getDAO: NamingException while getting DAO type : \n" + ne.getMessage()); } catch (Exception se) { throw new CatalogDAOSysException(" CatalogDAOFactory.getDAO: Exception while getting DAO type : \n" + se.getMessage()); } return catDao; } } CatalogDAOFactory 是典型的工厂方法, catDao 是通过动态类装入器 className 获得 CatalogDAOFactory 具体实现 子类,这个实现子类在 Java 宠物店是用来操作 catalog <em>数据</em>库,用户可以根据<em>数据</em>库的类型不同,定制自己的具体实现子类, 将自己的子类名给与 CATALOG_DAO_CLASS 变量就可以。 由此可见,工厂方法确实为系统结构提供了非常灵活强大的动态扩展机制,只要我们更换一下具体的工厂方法,系统其他 地方无需一点变换,就有可能将系统功能进行改头换面的变化。 设计模式之 Builder Builder 模式定义: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. Builder 模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构建它们.用户不知 道内部的具体构建细节.Builder 模式是非常类似抽象工厂模式,细微的区别大概只有在反复使用<em>中</em>才能体会到. 为何使用? 是为了将构建复杂对象的过程和它的部件解耦.注意: 是解耦过程和部件. 因为一个复杂的对象,不但有很多大量组成部分,如汽车,有很多部件:车轮 方向盘 发动机还有各种小零件等等,部件很多,但 远不止这些,如何将这些部件装配成一辆汽车,这个装配过程也很复杂(需要很好的组装技术),Builder 模式就是为了将部件和组装 过程分开. 如何使用? 首先假设一个复杂对象是由多个部件组成的,Builder 模式是把复杂对象的创建和部件的创建分别开来,分别用 Builder 类和 Director 类来表示. 首先,需要一个接口,它定义如何创建复杂对象的各个部件: public interface Builder { //创建部件 A 比如创建汽车车轮 void buildPartA(); //创建部件 B 比如创建汽车方向盘 void buildPartB(); //创建部件 C 比如创建汽车发动机 void buildPartC(); //返回最后组装成品结果 (返回最后装配好的汽车) //成品的组装过程不在这里进行,而是转移到下面的 Director 类<em>中</em>进行. //从而实现了解耦过程和部件 Product getResult(); } 用 Director 构建最后的复杂对象,而在上面 Builder 接口<em>中</em>封装的是如何创建一个个部件(复杂对象是由这些部件组成的),也就 是说 Director 的内容是如何将部件最后组装成成品: public class Director { private Builder builder; public Director( Builder builder ) { this.builder = builder; } // 将部件 partA partB partC 最后组成复杂对象 //这里是将车轮 方向盘和发动机组装成汽车的过程 public void construct() { builder.buildPartA(); builder.buildPartB(); builder.buildPartC(); } } Builder 的具体实现 ConcreteBuilder: 通过具体完成接口 Builder 来构建或装配产品的部件; 定义并明确它所要创建的是什么具体东西; 提供一个可以重新获取产品的接口: public class ConcreteBuilder implements Builder { Part partA, partB, partC; public void buildPartA() { //这里是具体如何构建 partA 的代码 }; public void buildPartB() { //这里是具体如何构建 partB 的代码 }; public void buildPartC() { //这里是具体如何构建 partB 的代码 }; public Product getResult() { //返回最后组装成品结果 }; } 复杂对象:产品 Product: public interface Product { } 复杂对象的部件: public interface Part { } 我们看看如何调用 Builder 模式: ConcreteBuilder builder = new ConcreteBuilder(); Director director = new Director( builder ); director.construct(); Product product = builder.getResult(); Builder 模式的应用 在 Java 实际使用<em>中</em>,我们经常用到"池"(Pool)的概念,当资源提供者无法提供足够的资源,并且这些资源需要被很多用户反复共 享时,就需要使用池. "池"实际是一段内存,当池<em>中</em>有一些复杂的资源的"断肢"(比如<em>数据</em>库的连接池,也许有时一个连接会<em>中</em>断),如果循环再利用这 些"断肢",将提高内存使用效率,提高池的性能.修改 Builder 模式<em>中</em> Director 类使之能诊断"断肢"断在哪个部件上,再修复这个部件. 设计模式之 Prototype(原型) 原型模式定义: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个 原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。 如何使用? 因为 Java <em>中</em>的提供 clone()方法来实现对象的克隆,所以 Prototype模式实现一下子变得很简单. 以勺子为例: public abstract class AbstractSpoon implements Cloneable { String spoonName; public void setSpoonName(String spoonName) {this.spoonName = spoonName;} public String getSpoonName() {return this.spoonName;} public Object clone() { Object object = null; try { object = super.clone(); } catch (CloneNotSupportedException exception) { System.err.println("AbstractSpoon is not Cloneable"); } return object; } } 有个具体实现(ConcretePrototype): public class SoupSpoon extends AbstractSpoon { public SoupSpoon() { setSpoonName("Soup Spoon"); } } 调用 Prototype 模式很简单: AbstractSpoon spoon = new SoupSpoon(); AbstractSpoon spoon2 = spoon.clone(); 当然也可以结合工厂模式来创建 AbstractSpoon 实例。 在 Java <em>中</em> Prototype 模式变成 clone()方法的使用,由于 Java 的纯洁的面向对象特性,使得在 Java <em>中</em>使用设计模式变 得很自然,两者已经几乎是浑然一体了。这反映在很多模式上,如 Interator 遍历模式。 设计模式之 Adapter(适配器) 适配器模式定义: 将两个不兼容的类纠合在一起使用,属于结构型模式,需要有 Adaptee(被适配者)和 Adaptor(适配器)两个身份. 为何使用? 我们经常碰到要将两个没有关系的类组合在一起使用,第一解决方案是:修改各自类的接口,但是如果我们没有源代码,或 者,我们不愿意为了一个应用而修改各自的接口。 怎么办? 使用 Adapter,在这两种接口之间创建一个混合接口(混血儿). 如何使用? 实现 Adapter 方式,其实"think in Java"的"类再生"一节<em>中</em>已经提到,有两种方式:组合(composition)和继承 (inheritance). 假设我们要打桩,有两种类:方形桩 圆形桩. public class SquarePeg{ public void insert(String str){ System.out.println("SquarePeg insert():"+str); } } public class RoundPeg{ public void insertIntohole(String msg){ System.out.println("RoundPeg insertIntoHole():"+msg); } } 现在有一个应用,需要既打方形桩,又打圆形桩.那么我们需要将这两个没有关系的类综合应用.假设 RoundPeg 我们没有源 代码,或源代码我们不想修改,那么我们使用 Adapter 来实现这个应用: public class PegAdapter extends SquarePeg{ private RoundPeg roundPeg; public PegAdapter(RoundPeg peg)(this.roundPeg=peg;) public void insert(String str){ roundPeg.insertIntoHole(str);} } 在上面代码<em>中</em>,RoundPeg 属于 Adaptee,是被适配者.PegAdapter 是 Adapter,将 Adaptee(被适配者 RoundPeg)和 Target(目标 SquarePeg)进行适配.实际上这是将组合方法(composition)和继承(inheritance)方法综合运用. PegAdapter 首先继承 SquarePeg,然后使用 new 的组合生成对象方式,生成 RoundPeg 的对象 roundPeg,再重载父 类 insert()方法。从这里,你也了解使用 new生成对象和使用 extends 继承生成对象的不同,前者无需对原来的类修改,甚至无 需要知道其内部结构和源代码. 如果你有些 Java 使用的经验,已经发现,这种模式经常使用。 进一步使用 上面的 PegAdapter 是继承了 SquarePeg,如果我们需要两边继承,即继承 SquarePeg 又继承 RoundPeg,因为 Java <em>中</em> 不允许多继承,但是我们可以实现(implements)两个接口(interface) public interface IRoundPeg{ public void insertIntoHole(String msg); } public interface ISquarePeg{ public void insert(String str); } 下面是新的 RoundPeg 和 SquarePeg, 除了实现接口这一区别,和上面的没什么区别。 public class SquarePeg implements ISquarePeg{ public void insert(String str){ System.out.println("SquarePeg insert():"+str); } } public class RoundPeg implements IRoundPeg{ public void insertIntohole(String msg){ System.out.println("RoundPeg insertIntoHole():"+msg); } } 下面是新的 PegAdapter,叫做 two-way adapter: public class PegAdapter implements IRoundPeg,ISquarePeg{ private RoundPeg roundPeg; private SquarePeg squarePeg; // 构造方法 public PegAdapter(RoundPeg peg){this.roundPeg=peg;} // 构造方法 public PegAdapter(SquarePeg peg)(this.squarePeg=peg;) public void insert(String str){ roundPeg.insertIntoHole(str);} } 还有一种叫 Pluggable Adapters,可以动态的获取几个 adapters <em>中</em>一个。使用 Reflection 技术,可以动态的发现类<em>中</em>的 Public 方法。 设计模式之 Proxy(代理) 理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用<em>中</em>,可以如鱼得水,享受游刃有余的乐趣. 代理模式是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,Proxy 是代理的意思,我们 也许有代理服务器等概念,代理概念可以解释为:在出发点到目的地之间有一道<em>中</em>间层,意为代理. 设计模式<em>中</em>定义: 为其他对象提供一种代理以控制对这个对象的访问. 为什么要使用 Proxy? 1.授权机制 不同级别的用户对同一对象拥有不同的访问权利,如 Jive 论坛系统<em>中</em>,就使用 Proxy 进行授权机制控制,访问 论坛有两种人:注册用户和游客(未注册用户),Jive <em>中</em>就通过类似 ForumProxy 这样的代理来控制这两种用户对论坛的访问权 限. 2.某个客户端不能直接操作到某个对象,但又必须和那个对象有所互动. 举例两个具体情况: (1)如果那个对象是一个是很大的图片,需要花费很长时间才能<em>显示</em>出来,那么当这个图片包含在文档<em>中</em>时,使用编辑器或浏 览器打开这个文档,打开文档必须很迅速,不能等待大图片处理完成,这时需要做个图片 Proxy 来代替真正的图片. (2)如果那个对象在 Internet 的某个远端服务器上,直接操作这个对象因为网络速度原因可能比较慢,那我们可以先用 Proxy来代替那个对象. 总之原则是,对于开销很大的对象,只有在使用它时才创建,这个原则可以为我们节省很多宝贵的 Java 内存. 所以,有些人认 为 Java 耗费资源内存,我以为这和程序编制思路也有一定的关系. 如何使用 Proxy? 以 Jive 论坛系统为例,访问论坛系统的用户有多种类型:注册普通用户 论坛管理者 系统管理者 游客,注册普通用户才能发 言;论坛管理者可以管理他被授权的论坛;系统管理者可以管理所有事务等,这些权限划分和管理是使用 Proxy完成的. Forum 是 Jive的核心接口,在 Forum <em>中</em>陈列了有关论坛操作的主要行为,如论坛名称 论坛描述的获取和修改,帖子发表删 除编辑等. 在 ForumPermissions <em>中</em>定义了各种级别权限的用户: public class ForumPermissions implements Cacheable { /** * Permission to read object. */ public static final int READ = 0; /** * Permission to administer the entire sytem. */ public static final int SYSTEM_ADMIN = 1; /** * Permission to administer a particular forum. */ public static final int FORUM_ADMIN = 2; /** * Permission to administer a particular user. */ public static final int USER_ADMIN = 3; /** * Permission to administer a particular group. */ public static final int GROUP_ADMIN = 4; /** * Permission to moderate threads. */ public static final int MODERATE_THREADS = 5; /** * Permission to create a new thread. */ public static final int CREATE_THREAD = 6; /** * Permission to create a new message. */ public static final int CREATE_MESSAGE = 7; /** * Permission to moderate messages. */ public static final int MODERATE_MESSAGES = 8; ..... public boolean isSystemOrForumAdmin() { return (values[FORUM_ADMIN] || values[SYSTEM_ADMIN]); } ..... } 因此,Forum <em>中</em>各种操作权限是和 ForumPermissions 定义的用户级别有关系的,作为接口 Forum 的实现:ForumProxy 正是将这种对应关系联系起来.比如,修改 Forum 的名称,只有论坛管理者或系统管理者可以修改,代码如下: public class ForumProxy implements Forum { private ForumPermissions permissions; private Forum forum; this.authorization = authorization; public ForumProxy(Forum forum, Authorization authorization, ForumPermissions permissions) { this.forum = forum; this.authorization = authorization; this.permissions = permissions; } ..... public void setName(String name) throws UnauthorizedException, ForumAlreadyExistsException { //只有是系统或论坛管理者才可以修改名称 if (permissions.isSystemOrForumAdmin()) { forum.setName(name); } else { throw new UnauthorizedException(); } } ... } 而 DbForum 才是接口 Forum 的真正实现,以修改论坛名称为例: public class DbForum implements Forum, Cacheable { ... public void setName(String name) throws ForumAlreadyExistsException { .... this.name = name; //这里真正将新名称保存到<em>数据</em>库<em>中</em> saveToDb(); .... } ... } 凡是涉及到对论坛名称修改这一事件,其他程序都首先得和ForumProxy打交道,由ForumProxy决定是否有权限做某一样 事情,ForumProxy 是个名副其实的"网关","安全代理系统". 在平时应用<em>中</em>,无可避免总要涉及到系统的授权或安全体系,不管你有无意识的使用 Proxy,实际你已经在使用 Proxy了. 我们继续结合 Jive谈入深一点,下面要涉及到工厂模式了,如果你不了解工厂模式,请看我的另外一篇文章:设计模式之 Factory 我们已经知道,使用 Forum 需要通过 ForumProxy,Jive <em>中</em>创建一个 Forum 是使用 Factory 模式,有一个总的抽象类 ForumFactory,在这个抽象类<em>中</em>,调用 ForumFactory 是通过 getInstance()方法实现,这里使用了 Singleton(也是设计模式 之一,由于介绍文章很多,我就不写了),getInstance()返回的是 ForumFactoryProxy. 为什么不返回 ForumFactory,而返回 ForumFactory 的实现 ForumFactoryProxy? 原因是明显的,需要通过代理确定是否有权限创建 forum. 在 ForumFactoryProxy <em>中</em>我们看到代码如下: public class ForumFactoryProxy extends ForumFactory { protected ForumFactory factory; protected Authorization authorization; protected ForumPermissions permissions; public ForumFactoryProxy(Authorization authorization, ForumFactory factory, ForumPermissions permissions) { this.factory = factory; this.authorization = authorization; this.permissions = permissions; } public Forum createForum(String name, String description) throws UnauthorizedException, ForumAlreadyExistsException { //只有系统管理者才可以创建 forum if (permissions.get(ForumPermissions.SYSTEM_ADMIN)) { Forum newForum = factory.createForum(name, description); return new ForumProxy(newForum, authorization, permissions); } else { throw new UnauthorizedException(); } } 方法 createForum 返回的也是 ForumProxy, Proxy 就象一道墙,其他程序只能和 Proxy交互操作. 注意到这里有两个 Proxy:ForumProxy 和 ForumFactoryProxy. 代表两个不同的职责:使用 Forum 和创建 Forum; 至于为什么将使用对象和创建对象分开,这也是为什么使用 Factory 模式的原因所在:是为了"封装" "分派";换句话说,尽可 能功能单一化,方便维护修改. Jive论坛系统<em>中</em>其他如帖子的创建和使用,都是按照 Forum 这个思路而来的. 以上我们讨论了如何使用Proxy进行授权机制的访问,Proxy还可以对用户隐藏另外一种称为copy-on-write的优化方式. 拷贝一个庞大而复杂的对象是一个开销很大的操作,如果拷贝过程<em>中</em>,没有对原来的对象有所修改,那么这样的拷贝开销就没有必 要.用代理延迟这一拷贝过程. 比如:我们有一个很大的 Collection,具体如 hashtable,有很多客户端会并发同时访问它.其<em>中</em>一个特别的客户端要进行连 续的<em>数据</em>获取,此时要求其他客户端不能再向 hashtable <em>中</em>增加或删除 东东. 最直接的解决方案是:使用 collection 的 lock,让这特别的客户端获得这个 lock,进行连续的<em>数据</em>获取,然后再释放 lock. public void foFetches(Hashtable ht){ synchronized(ht){ //具体的连续<em>数据</em>获取动作.. } } 但是这一办法可能锁住 Collection 会很长时间,这段时间,其他客户端就不能访问该 Collection 了. 第二个解决方案是clone这个Collection,然后让连续的<em>数据</em>获取针对clone出来的那个Collection操作.这个方案前提是, 这个 Collection 是可 clone的,而且必须有提供深度 clone的方法.Hashtable 就提供了对自己的 clone方法,但不是 Key和 value对象的 clone,关于 Clone含义可以参考专门文章. public void foFetches(Hashtable ht){ Hashttable newht=(Hashtable)ht.clone(); } 问题又来了,由于是针对clone出来的对象操作,如果原来的母体被其他客户端操作修改了, 那么对clone出来的对象操作就 没有意义了. 最后解决方案:我们可以等其他客户端修改完成后再进行 clone,也就是说,这个特别的客户端先通过调用一个叫 clone的方 法来进行一系列<em>数据</em>获取操作.但实际上没有真正的进行对象拷贝,直至有其他客户端修改了这个对象 Collection. 使用 Proxy实现这个方案.这就是 copy-on-write操作. Proxy应用范围很广,现在流行的分布计算方式 RMI 和 Corba 等都是 Proxy模式的应用. 更多 Proxy应用,见 http://www.research.umbc.edu/~tarr/cs491/lectures/Proxy.pdf Sun 公司的 Explore the Dynamic Proxy API Dynamic Proxy Classes 设计模式之 Facade(外观 总管 Manager) Facade 模式的定义: 为子系统<em>中</em>的一组接口提供一个一致的界面. Facade一个典型应用就是<em>数据</em>库 JDBC 的应用,如下例对<em>数据</em>库的操作: public class DBCompare { Connection conn = null; PreparedStatement prep = null; ResultSet rset = null; try { Class.forName( "<driver>" ).newInstance(); conn = DriverManager.getConnection( "<database>" ); String sql = "SELECT * FROM <table> WHERE <column name> = ?"; prep = conn.prepareStatement( sql ); prep.setString( 1, "<column value>" ); rset = prep.executeQuery(); if( rset.next() ) { System.out.println( rset.getString( "<column name" ) ); } } catch( SException e ) { e.printStackTrace(); } finally { rset.close(); prep.close(); conn.close(); } } 上例是 Jsp <em>中</em>最通常的对<em>数据</em>库操作办法. 在应用<em>中</em>,经常需要对<em>数据</em>库操作,每次都写上述一段代码肯定比较麻烦,需要将其<em>中</em>不变的部分提炼出来,做成一个接口,这 就引入了 facade 外观对象.如果以后我们更换 Class.forName <em>中</em>的<driver>也非常方便,比如从 Mysql <em>数据</em>库换到 Oracle <em>数据</em>库,只要更换 facade接口<em>中</em>的 driver 就可以. 我们做成了一个 Facade 接口,使用该接口,上例<em>中</em>的程序就可以更改如下: public class DBCompare { String sql = "SELECT * FROM <table> WHERE <column name> = ?"; try { Mysql msql=new mysql(sql); prep.setString( 1, "<column value>" ); rset = prep.executeQuery(); if( rset.next() ) { System.out.println( rset.getString( "<column name" ) ); } } catch( SException e ) { e.printStackTrace(); } finally { mysql.close(); mysql=null; } } 可见非常简单,所有程序对<em>数据</em>库访问都是使用改接口,降低系统的复杂性,增加了灵活性. 如果我们要使用连接池,也只要针对 facade接口修改就可以. 由上图可以看出, facade实际上是个理顺系统间关系,降低系统间耦合度的一个常用的办法,也许你已经不知不觉在使用,尽 管不知道它就是 facade. 设计模式之 Composite(组合) Composite 模式定义: 将对象以<em>树形</em>结构组织起来,以达成“部分-整体” 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性. Composite比较容易理解,想到 Composite 就应该想到<em>树形</em>结构图。组合体内这些对象都有共同接口,当组合体一个对象 的方法被调用执行时,Composite 将遍历(Iterator)整个<em>树形</em>结构,寻找同样包含这个方法的对象并实现调用执行。可以用牵一 动百来形容。 所以 Composite 模式使用到 Iterator 模式,和 Chain of Responsibility 模式类似。 Composite 好处: 1.使客户端调用简单,客户端可以一致的使用组合结构或其<em>中</em>单个对象,用户就不必关系自己处理的是单个对象还是整个 组合结构,这就简化了客户端代码。 2.更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。 如何使用 Composite? 首先定义一个接口或抽象类,这是设计模式通用方式了,其他设计模式对接口内部定义限制不多, Composite 却有个规定, 那就是要在接口内部定义一个用于访问和管理 Composite组合体的对象们(或称部件 Component). 下面的代码是以抽象类定义,一般尽量用接口 interface, public abstract class Equipment { private String name; //实价 public abstract double netPrice(); //折扣价格 public abstract double discountPrice(); //增加部件方法 public boolean add(Equipment equipment) { return false; } //删除部件方法 public boolean remove(Equipment equipment) { return false; } //注意这里,这里就提供一种用于访问组合体类的部件方法。 public Iterator iter() { return null; } public Equipment(final String name) { this.name=name; } } 抽象类 Equipment 就是 Component 定义,代表着组合体类的对象们,Equipment <em>中</em>定义几个共同的方法。 public class Disk extends Equipment { public Disk(String name) { super(name); } //定义 Disk 实价为 1 public double netPrice() { return 1.; } //定义了 disk 折扣价格是 0.5 对折。 public double discountPrice() { return .5; } } Disk是组合体内的一个对象,或称一个部件,这个部件是个单独元素( Primitive)。 还有一种可能是,一个部件也是一个组合体,就是说这个部件下面还有'儿子',这是<em>树形</em>结构<em>中</em>通常的情况,应该比较容易理解。 现在我们先要定义这个组合体: abstract class CompositeEquipment extends Equipment { private int i=0; //定义一个 Vector 用来存放'儿子' private Lsit equipment=new ArrayList(); public CompositeEquipment(String name) { super(name); } public boolean add(Equipment equipment) { this.equipment.add(equipment); return true; } public double netPrice() { double netPrice=0.; Iterator iter=equipment.iterator(); for(iter.hasNext()) netPrice+=((Equipment)iter.next()).netPrice(); return netPrice; } public double discountPrice() { double discountPrice=0.; Iterator iter=equipment.iterator(); for(iter.hasNext()) discountPrice+=((Equipment)iter.next()).discountPrice(); return discountPrice; } //注意这里,这里就提供用于访问自己组合体内的部件方法。 //上面 dIsk 之所以没有,是因为 Disk 是个单独(Primitive)的元素. public Iterator iter() { return equipment.iterator() ; { //重载 Iterator 方法 public boolean hasNext() { return i<equipment.size(); } //重载 Iterator 方法 public Object next() { if(hasNext()) return equipment.elementAt(i++); else throw new NoSuchElementException(); } } 上面 CompositeEquipment 继承了 Equipment,同时为自己里面的对象们提供了外部访问的方法,重载了 Iterator,Iterator 是 Java 的 Collection 的一个接口,是 Iterator 模式的实现. 我们再看看 CompositeEquipment 的两个具体类:盘盒 Chassis 和箱子 Cabinet,箱子里面可以放很多东西,如底板, 电源盒,硬盘盒等;盘盒里面可以放一些小设备,如硬盘 软驱等。无疑这两个都是属于组合体性质的。 public class Chassis extends CompositeEquipment { public Chassis(String name) { super(name); } public double netPrice() { return 1.+super.netPrice(); } public double discountPrice() { return .5+super.discountPrice(); } } public class Cabinet extends CompositeEquipment { public Cabinet(String name) { super(name); } public double netPrice() { return 1.+super.netPrice(); } public double discountPrice() { return .5+super.discountPrice(); } } 至此我们完成了整个 Composite模式的架构。 我们可以看看客户端调用 Composote 代码: Cabinet cabinet=new Cabinet("Tower"); Chassis chassis=new Chassis("PC Chassis"); //将 PC Chassis 装到 Tower <em>中</em> (将盘盒装到箱子里) cabinet.add(chassis); //将一个 10GB 的硬盘装到 PC Chassis (将硬盘装到盘盒里) chassis.add(new Disk("10 GB")); //调用 netPrice()方法; System.out.println("netPrice="+cabinet.netPrice()); System.out.println("discountPrice="+cabinet.discountPrice()); 上面调用的方法 netPrice()或 discountPrice(),实际上 Composite 使用 Iterator 遍历了整个<em>树形</em>结构,寻找同样包含这 个方法的对象并实现调用执行. Composite是个很巧妙体现智慧的模式,在实际应用<em>中</em>,如果碰到<em>树形</em>结构,我们就可以尝试是否可以使用这个模式。 以论坛为例,一个版(forum)<em>中</em>有很多帖子(message),这些帖子有原始贴,有对原始贴的回应贴,是个典型的<em>树形</em>结构, 那么当然可以使用 Composite模式,那么我们进入 Jive<em>中</em>看看,是如何实现的. Jive 解剖 在 Jive<em>中</em> ForumThread 是 ForumMessages 的容器 container(组合体).也就是说,ForumThread 类似我们上例<em>中</em>的 CompositeEquipment.它和 messages 的关系如图: [thread] |- [message] |- [message] |- [message] |- [message] |- [message] 我们在 ForumThread 看到如下代码: public interface ForumThread { .... public void addMessage(ForumMessage parentMessage, ForumMessage newMessage) throws UnauthorizedException; public void deleteMessage(ForumMessage message) throws UnauthorizedException; public Iterator messages(); .... } 类似 CompositeEquipment, 提供用于访问自己组合体内的部件方法: 增加 删除 遍历. 结合我的其他模式<em>中</em>对 Jive的分析,我们已经基本大体理解了 Jive 论坛体系的框架,如果你之前不理解设计模式,而直接去看 Jive源代码,你肯定无法看懂。 参考文章: Composite 模式和<em>树形</em>结构的讨论 设计模式之 Decorator(油漆工) 装饰模式:Decorator 常被翻译成"装饰",我觉得翻译成"油漆工"更形象点,油漆工(decorator)是用来刷油漆的,那么被刷油漆的 对象我们称 decoratee.这两种实体在 Decorator 模式<em>中</em>是必须的. Decorator定义: 动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用 Decorator 模式相比用生成子类方式达到功能的扩充显得更为灵 活. 为什么使用 Decorator? 我们通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性, 同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的. 使用Decorator的理由是:这些功能需要由用户动态决定加入的方式和时机.Decorator提供了"即插即用"的方法,在运行期间决 定何时增加何种功能. 如何使用? 举Adapter <em>中</em>的打桩示例,在 Adapter <em>中</em>有两种类:方形桩 圆形桩,Adapter模式展示如何综合使用这两个类,在Decorator模 式<em>中</em>,我们是要在打桩时增加一些额外功能,比如,挖坑 在桩上钉木板等,不关心如何使用两个不相关的类. 我们先建立一个接口: public interface Work { public void insert(); } 接口 Work有一个具体实现:插入方形桩或圆形桩,这两个区别对 Decorator 是无所谓.我们以插入方形桩为例: public class SquarePeg implements Work{ public void insert(){ System.out.println("方形桩插入"); } } 现在有一个应用:需要在桩打入前,挖坑,在打入后,在桩上钉木板,这些额外的功能是动态,可能随意增加调整修改,比如,可能又需 要在打桩之后钉架子(只是比喻). 那么我们使用 Decorator 模式,这里方形桩 SquarePeg 是 decoratee(被刷油漆者),我们需要在 decoratee 上刷些"油漆",这 些油漆就是那些额外的功能. public class Decorator implements Work{ private Work work; //额外增加的功能被打包在这个 List <em>中</em> private ArrayList others = new ArrayList(); //在构造器<em>中</em>使用组合 new方式,引入 Work 对象; public Decorator(Work work) { this.work=work; others.add("挖坑"); others.add("钉木板"); } public void insert(){ newMethod(); } //在新方法<em>中</em>,我们在 insert 之前增加其他方法,这里次序先后是用户灵活指定的 public void newMethod() { otherMethod(); work.insert(); } public void otherMethod() { ListIterator listIterator = others.listIterator(); while (listIterator.hasNext()) { System.out.println(((String)(listIterator.next())) + " 正在进行"); } } } 在上例<em>中</em>,我们把挖坑和钉木板都排在了打桩 insert 前面,这里只是举例说明额外功能次序可以任意安排. 好了,Decorator 模式出来了,我们看如何调用: Work squarePeg = new SquarePeg(); Work decorator = new Decorator(squarePeg); decorator.insert(); Decorator 模式至此完成. 如果你细心,会发现,上面调用类似我们读取文件时的调用: FileReader fr = new FileReader(filename); BufferedReader br = new BufferedReader(fr); 实际上 Java 的 I/O API 就是使用 Decorator 实现的,I/O变种很多,如果都采取继承方法,将会产生很多子类,显然相当繁琐. Jive <em>中</em>的 Decorator 实现 在论坛系统<em>中</em>,有些特别的字是不能出现在论坛<em>中</em>如"打倒 XXX",我们需要过滤这些"反动"的字体.不让他们出现或者高亮度显 示. 在 IBM Java 专栏<em>中</em>专门谈 Jive的文章<em>中</em>,有谈及 Jive<em>中</em> ForumMessageFilter.java 使用了 Decorator 模式,其实,该程序并 没有真正使用 Decorator,而是提示说:针对特别论坛可以设计额外增加的过滤功能,那么就可以重组 ForumMessageFilter 作 为 Decorator 模式了. 所以,我们在分辨是否真正是Decorator模式,以及会真正使用Decorator模式,一定要把握好Decorator模式的定义,以及其<em>中</em> 参与的角色(Decoratee 和 Decorator). 设计模式之 Bridge Bridge 模式定义 :将抽象和行为划分开来,各自独立,但能动态的结合。 任何事物对象都有抽象和行为之分,例如人,人是一种抽象,人分男人和女人等;人有行为,行为也有各种具体表现,所 以,“人”与“人的行为”两个概念也反映了抽象和行为之分。 在面向对象设计的基本概念<em>中</em>,对象这个概念实际是由属性和行为两个部分组成的,属性我们可以认为是一种静止的,是 一种抽象,一般情况下,行为是包含在一个对象<em>中</em>,但是,在有的情况下,我们需要将这些行为也进行归类,形成一个总的行 为接口,这就是桥模式的用处。 为什么使用? 不希望抽象部分和行为有一种固定的绑定关系,而是应该可以动态联系的。 如果一个抽象类或接口有多个具体实现(子类、concrete subclass),这些子类之间关系可能有以下两种情况: 1. 这多个子类之间概念是并列的,如前面举例,打桩,有两个 concrete class:方形桩和圆形桩;这两个形状上的桩是并列的, 没有概念上的重复。 2.这多个子类之<em>中</em>有内容概念上重叠.那么需要我们把抽象共同部分和行为共同部分各自独立开来,原来是准备放在一个接 口里,现在需要设计两个接口:抽象接口和行为接口,分别放置抽象和行为. 例如,一杯咖啡为例,子类实现类为四个:<em>中</em>杯加奶、大杯加奶、 <em>中</em>杯不加奶、大杯不加奶。 但是,我们注意到:上面四个子类<em>中</em>有概念重叠,可从另外一个角度进行考虑,这四个类实际是两个角色的组合:抽象 和 行为,其<em>中</em>抽象为:<em>中</em>杯和大杯;行为为:加奶 不加奶(如加橙汁 加苹果汁). 实现四个子类在抽象和行为之间发生了固定的绑定关系,如果以后动态增加加葡萄汁的行为,就必须再增加两个类:<em>中</em>杯 加葡萄汁和大杯加葡萄汁。显然混乱,扩展性极差。 那我们从分离抽象和行为的角度,使用 Bridge模式来实现。 如何实现?</a></div><div data-report-view="{"mod":"popu_645","index":"5","dest":"https://download.csdn.net/download/sunnybuer/15117746","strategy":"2~default~OPENSEARCH~Rate","extra":"{\"utm_medium\":\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-5-15117746-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\",\"dist_request_id\":\"1713920331325_95453\"}","spm":"1035.2023.3001.6557"}" class="list-item" data-v-ca2d15ac><div class="recommend-title" data-v-ca2d15ac><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAltJREFUWEdjZGBgYGhv/yD45//nEEYGBrX//xj4QWK0AoxMDB//MzDcYmHkXVNZKfCeEWz5v8/1DP8ZuGhlKVZzGRm+sTDxNjI2tz1OZfjHYEpXy2GWMTGcZmxpe9xN62DH5TlQdDA2tzyeNSC+h1o66gCyQyApUdRNSIhNGBSS7979ejtv/utd5EQl2Q7IypT0ExJiFoc44O/LadOfbxp1wPAOAWlpdr5Pn//8/Pzp70+QT3GlAX5+ZnYeHhb2p09/fiImRIhOhBYWvIo21ryWu/Z8PHDp4tdn2BxgoM8l4+IiYH/k6OdjJ058vk91B7g487swMDD8v3Hj+2VJSTYpfn5mEZAlHz/9ffPq5e+Xqqoc2iD+nr0f99DSAQQ9RhMHcHAwsYSGCtvKy7Gr4HPBo0c/b69c/fbwzx///hJ0KQMDA9FpAGaYizO/tpkZjwUTEyMTsgX//v3/d/LUl+N79368RozFMDUkOwCkUUODU8zHW9CFg4OJG8T/8ePf181b3u25efPHK1IsB6nF6gAjY25ZEWFWcNPs169/fw4c+HQD3WBBIRaOsBAhZ5D4qjXv9r5/9+cHuhoHBz4NNjYmFpD4m7e/P547+/UxuhqsDoiPE3WWlWVXgvju/5ee3qfLsfmMiZmBEST+7y/Df2zyJcXSkRwcjDwgucePf95buOj1Xqo6gFBwDw8H/P/P8O/nz//fCPkWmzw7OyMXIyMDOLeQHQXkWIxNz9BygJubgI6kBCu4tUMt8PzF75e7dn24QlQuoJalxJgzCDomA901G/DOKSieBrJ7DgCPdYFAskV/NwAAAABJRU5ErkJggg==" alt data-v-ca2d15ac> <a target="_blank" href="https://download.csdn.net/download/sunnybuer/15117746" data-report-click="{"mod":"popu_645","index":"5","dest":"https://download.csdn.net/download/sunnybuer/15117746","strategy":"2~default~OPENSEARCH~Rate","extra":"{\"utm_medium\":\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-5-15117746-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\",\"dist_request_id\":\"1713920331325_95453\"}","spm":"1035.2023.3001.6557"}" data-report-query="spm=1035.2023.3001.6557&utm_medium=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-5-15117746-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default&depth_1-utm_source=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-5-15117746-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default" class="title" data-v-ca2d15ac>C# Winform<em>数据</em>库应用设计(附开发案例</a></div> <a target="_blank" href="https://download.csdn.net/download/sunnybuer/15117746" data-report-click="{"mod":"popu_645","index":"5","dest":"https://download.csdn.net/download/sunnybuer/15117746","strategy":"2~default~OPENSEARCH~Rate","extra":"{\"utm_medium\":\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-5-15117746-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\",\"dist_request_id\":\"1713920331325_95453\"}","spm":"1035.2023.3001.6557"}" data-report-query="spm=1035.2023.3001.6557&utm_medium=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-5-15117746-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default&depth_1-utm_source=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-5-15117746-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default" class="desc" data-v-ca2d15ac>c#编程集合资料,不错的应用设计,另附一些开发案例的下载地址,欢迎大家下载学习。 学习完本课程之后,我们需要达到以下目标: (1) 掌握基本的C#语法,熟练运用C#编写基本的程序逻辑。 (2) 能够创建C#控制台应用程序并处理输入输出。 (3) 掌握C#<em>中</em>的数组,并对数组进行相应的排序,查找操作。 (4) 熟练使用C#的字符串对象。 (5) 掌握Windows窗体应用程序的创建,能熟练使用常用的控件设计窗体界面。 (6) 掌握MDI应用程序的开发步骤。 (7) 了解ADO.NET的组成和工作原理。 (8) 通过ADO.NET访问对C#项目开发全程实录视频教程(全10个案例):htt: /cnrdn com/gCxC 课程说明… 第1章C#语法基础…… 核心技能部分 1.1 Net与C#概述. 111Net与C#的产生与应用 1.1.2 Visual studio 10 1.1.3创建C井应用程序 12 2C#语言基础 16 121变量与常量…16 12.2运算符和表达式 19 123C#语言<em>中</em>的注释 1.2.4使用 Console处理输入输出 21 1.3 C#语句结构 25 131条件语句 .25 132循环结构 32 任务实训部分.… 38 1:根据时间输出问候信息…… 38 2:三个数字比较大小 39 3:判断用户输入的字母 .40 输出裴波那契数列…… 翻着音 40 巩固练习 第2章嵌套循环和数组. 44 核心技能部分… .45 2.1 VS2008<em>中</em>的调试技巧 45 2.2 嵌套循环 47 2.3 数组. 50 231数组的定义 50 232数组的基木操作 50 233数组的排序 51 任务实训部分… 55 1打印等腰三角形 55 2:数组的操作 56 3:数组的排序。 错误!定义书签 4:数组的排序 错误!未定义书签 巩固练习 57 第3章方法与字符串 59 C#项目开发全程实录视频教程(全10个案例):htt: /cnrdn com/gCxC 核心技能部分 使用方法 311方法的定义 312方法的调用 63 313参数传递 String类 321C#语言<em>中</em>常用的字符串处理方法... 68 322格式字符串 32.3 String Builder类. 3.3 类型转换…14 331隐式转换 74 332显式转换.…… 74 333常用类型转换方法… 7 任务实训部分 77 1:方法的使用 2:从邮件地址提取用广名 80 3:网址类型分析 81 4:字符串转换 82 巩固练习. 84 第4章指导学习:阶段总结 86 知识总结 翻着 .:::a:a:.:::a:B:a:::::..aa:::.:.aa:.:aa::: 86 41.1核心技能目标 86 412知识体系总结… 86 4.2 综合实训 任务1:制作月份日历 任务2:数组<em>数据</em>添加和排序. 错误!未定义书签 任务3:自杀游戏… 错误未定义书签。 第5章 Win form常用控件 核心技能部分 90 创建 Windows应用稈序 90 511 Windows应用程序概述. 90 512创建第一个 Windows应用程序 5.13项目结构分析 5,2 Windows窗体….97 5.,21窗体<em>中</em>的常用属性. 98 522窗体<em>中</em>的常用事件…… 99 Windows窗体<em>中</em>的常用控件 9 C#项目开发全程实录视频教程(全10个案例):htt: /cnrdn com/gCxC 5.31 Winform控件公共属性… 532标签Labe) 01 533文本框( TextBox) ·,, 101 534按钮( Button)…102 535列表框 ListBox) 102 536组合框 Combobox) 103 53.7单选按钮( Radio Button)和复选框( CheckBox) 104 538图片框( Pictruebo×)..105 54用 Message Box类<em>显示</em>消息窗口 541消息框的<em>显示</em>……106 5.4.2消息框的返回值 107 综合案例:职员信息管理. 109 仟务实训部分…… 115 1:ATM信息查询 115 2:编写建表向导窗体…… 3:火车票预定程厅… 124 巩固练习… 第6章 MD窗体应用程序设计… 核心技能部分…… 130 6.1 SD窗体和MD窗体应用程序简介. 错误!未定义书签。 6.2 单文档应用程序的创建 30 62.1菜单栏( Menustrip) 130 622菜单栏的创建 130 623上下文菜单 ContextMenuStrip) 6.3 多文档应用程序 错误!未定义书签。 631创建多文档界面应用程序. 错误!未定义书签 632排列子窗口 错误未定义书签。 64图像列表( mageList控件… 134 65工具栏( ToolStrip控件) 135 66 状态( StatusStrip) 138 67选项卡( TabControl Timer控件 69 MD综合示例 错误!定义书签 任务实训部分……143 1创建记事本”应用程序 错误!未定义书签 2:增强”记事本”功能∴ 143 3:实现记事本字体样式设置… 144 C#项目开发全程实录视频教程(全10个案例):htt: /cnrdn com/gCxC 4:变色窗体 巩固练习……… 1448 第7章 使用 ADO. NET完成简单的<em>数据</em>库操作…. ·,, 150 核心技能部分 151 ADO. NET概述 151 1 ADO.NET的简介 151 7.12 ADO.NET的优点 152 713 ADO.NET的结 52 NET Framework<em>数据</em>提供程序 1154 7.21 Connection对象…………………………155 72.2使用 Connection对象链接到<em>数据</em>库 7.3异常操作 57 731try和 catch块 158 732<em>数据</em>库链接示例 Command对象 ∴161 741 Command对象简介 161 742 Command综合示例 任务实训部分 1:实现进销存系统用户注册 168 2:实现进销存系统用户登录.… 171 3:实现用户的删除功能…… .:.::::::.:...:::.:.:a.::::.:::::::::.:::.:::::::.:::.: 172 巩固练习 174 第8章使用 Data Reader完成查询功能 177 核心技能部分… 178 8.1 DataReader对象 811 Data reader对象简介 178 812 Data Reader对象常用的属性和方法 813 Data reader对象的使用 179 8.2 控件 81 821 Listview控件介绍…… 81 822 Listview控件的使用 <em>数据</em>库操作综合示例 187 任务实训部分…… L94 1:使用 Listview控件查询部门员工信息… 94 2:部门员工信息删除和修改 3:实现员工信息模糊查询... 203 巩固练习 204 C#项目开发全程实录视频教程(全10个案例):htt: /cnrdn com/gCxC 第9章 使用 Dataset实现断开式<em>数据</em>访问 206 核心技能部分.… 207 91<em>数据</em>集( Dataset) ·,, 207 911<em>数据</em>集( DataSet)简介…207 912<em>数据</em>集的结构 08 91.3<em>数据</em>集的工作原理 914创建 Data set对象…… 211 9,2 DataAdapter对象1211 92.1 DataAdapter对象简介… 211 922 DataAdapter对象的使用.. 213 3 Datagridview控什的使用 219 931 Data gridview控件简介 219 932 Datagridview控件的使用. 221 9 综合示例 226 仟务实训部分.… 229 1:航班查询窗体设计 29 2:<em>显示</em>所有航班信息 232 3:根据两地査询航班 .233 4:航班详细信息查询 234 巩固练习 235 第10章课程总复习… …)误!未定义书签。 101知识总结 错误!未定义书签 1011核心技能目标 错误!定义书签。 101.2知识体系总结 错误!未定义书签。 02任务实训 错误!未定义书签。 第11章项目案例:酒店管理系统…… 错误!未定义书签 111训练技能点…… 错误未定义书签。 112需求说明 错误!未定义书签 113设计与思路分析 错误未定义书签 113.1系统功能分析 错误!未定义书签。 1132<em>数据</em>库设计 错误!定义书签。 114实现步骤…… 错误!未定义书签 115时间分配 错误!定义书签 C#项目开发全程实录视频教程(全10个案例):htt: /cnrdn com/gCxC 第1章C#语法基础 学习内容 c#的发展史 C#的基本语法 C#的流程控制语句 俨能力目标 掌握仗用S2008开发C#NET控制台应用程序 掌握C#语言的基本语法 掌握c#的程序流程控制语句 C#项目开发全程实录视频教程(全10个案例):htt: /cnrdn com/gCxC 本章简介 从本门课开始我们将要开始学习¢#语言和NET平台。本章将使学员对NET和¢#有一个 初步的认识,了解C#的开发环境,编写第一个C#控制台应用程序。C#语言的基本语法和我 们之前的学习的C语言、Java语言一样同属于C语言语法系列,有很多相似的地方,同时也 有一些不同的地方,因此我们在学习的时候需要注意它们之间的区别,不要混淆。在本章<em>中</em>, 我们需要掌握c#<em>中</em>的变量、<em>数据</em>类型、运算符、条件、分攴、循环等基C排基础语法,这些 语言层血的知识是我们编写所有程序的基础,因此必须牢固掌握。 核心技能部分 1.1Net与C#概述 1.1.1Net与C#的产生与应用 1. Anders Hejlsberg-C#之父 Anders hejlsberg原木是曾经大名鼎鼎的 Borland公司的一员,他曾经编写了 Pasca编译 器,又把 Turbo pascal变为面向对象的 Object Pascal,并以此为基础开发了轰动全球、盛极 时的廾发工具 Delphi,为 Boland公司赚了个盆钵满盈。 随着 Delphi日渐成熟, Anders的兴趣转向了Java领域,他在」ava开发领域扩展方面有 很多自己独特的想法,并想在此领域大展宏图,但 Borland的经营者们还要靠他这棵“摇 钱树”继续在 Delphi上人肆捞金,所以他有一段郁郁不得志。 比尔盖茨三顾茅庐,力邀 Anders hejlsberg,并许以重金和宽松的环境,终于把 Anders 挖到了微软的旗下,其后由其主持设计,在2000年6月发布了新的开发语言C#(读做C Sharp),此后微软在2002年推出了 Microsoft net开发平台。 3 1.1.1 Anders He jlsberg C#项目开发全程实录视频教程(全10个案例):http://cnrdn.com/gcxc 2.C#语及其特点 与Java一样,C#语言是一个完全的面向对象语言,它继承了C++、Java和 Delphi的优 点,又借鉴了VB的简单易学。体现了当今最新的程序设计技术的功能和精华。C#继承了C 语言的语法风柊,同时又继承了C+的面冋对象特性。不同的是,c#的对象模犁己经面向 Internet进行了重新设计,使用的是NET框架的类库;C#不再提供对指针类型的支持,使得 程序不能随便访问内存地址空间,从而更加健壮;C#不再支持多重继承,避免了以往类层次 结构<em>中</em>由于多重继承带来的可怕后果。NET框架为C#提供了一个强大的、易用的、逻辑结 构一致的程序设计环境。同时,公共语言运行时( Common Language runtime)为C#程序语 言提供了一个托管的运行时环境,使程序比以往更加稳定、安全。其特点有: 语言简洁。 保留了C++的强大功能 快速应用廾发功能 语言的自由性 强大的<em>Web</em>服务器控件。 支持跨平台 与XML相融合 如果之前没有其他话言的编程经验,使用c#语言编程将是一个良好的开端。如果有其 他语言的编程基础,程序员将发现¢#语言除了像ⅤB一样简单易学外,还是一种拥有强大 功能的语言。而且 ASP NET平台也是完仝通过c#语言开发的,这决定了C语言得天独厚的 优势。但在任何情况下,C#语言都不可能孤立地使用,它必须同 Microsoft. net framework 起使用,因为使用C#语言编写的所有代码总是在 Microsoft .net framework<em>中</em>运行。 1.1.2 Visual studio 微软针对Net推岀了功能强大的集成丌发环境来支持开发人员的№et应用程序丌发,这 就是 Visual studio,它是目前最主要的Net平台开发环境。VS集成了 NET Framework和Net 开发插件,可以用来进行几乎所有Net应用程序的设计和开发L作,如 Windows应用程序 <em>Web</em>应用稈序、 Windows服务、智能设备应用程序等。 随着 NET Framework的不断升级, Visua| Studio也在不断升级,其发展历程可以用表1-1-1 来说明 表1-1-1Vs发展历程 年代 2002 2003 2005 2008 2010 廾发工具版木Vs2002 VS2003 VS2005 VS2008 VS2010 Net 1.0 1.1 2.0 3.5 4.0 Framework 由于本学期的知识点主要集<em>中</em>在C#的基本语法、 Win forms开发和 ADO. NET,这些知识</a></div></div></div></div> <div class="public_pc_right_footer2020" style="display:none;" data-v-4a5a7f56></div></div> <div id="right-floor-user-content_562" data-editor="{"type":"floor","pageId":143,"floorId":562}" class="user-right-floor right-box main-box detail-user-right" data-v-229a00b0><div class="__vuescroll" style="height:100%;width:100%;padding:0;position:relative;overflow:hidden;"><div class="__panel __hidebar" style="position:relative;box-sizing:border-box;height:100%;overflow-y:hidden;overflow-x:hidden;transform-origin:;transform:;"><div class="__view" style="position:relative;box-sizing:border-box;min-width:100%;min-height:100%;"><!----><div comp-data="[object Object]" baseInfo="[object Object]" community="[object Object]" class="introduce" data-v-4722a3ae><div class="introduce-title" data-v-4722a3ae><div class="img-info" data-v-4722a3ae><a href="https://bbs.csdn.net/forums/DotNET" class="community-img" data-v-4722a3ae><img src="https://img-community.csdnimg.cn/avatar/745f64491f2744dcbce3cd7127270b93.png?x-oss-process=image/resize,m_fixed,h_88,w_88" alt data-v-4722a3ae> <div title=".NET社区" class="community-name" data-v-4722a3ae> .NET社区 </div></a></div></div> <div class="content" data-v-4722a3ae><div class="detail" data-v-4722a3ae><div title="62046" class="item" data-v-4722a3ae><p class="num" data-v-4722a3ae> 62,046 </p> <p class="desc" data-v-4722a3ae> 社区成员 </p></div> <div title="669049" class="item" data-v-4722a3ae><a href="https://bbs.csdn.net/forums/DotNET" target="_blank" data-v-4722a3ae><p class="num" data-v-4722a3ae> 669,049 </p> <p class="desc" data-v-4722a3ae> 社区内容 </p></a></div></div> <div class="detail-btns" data-v-4722a3ae><div class="community-ctrl-btns_wrapper" data-v-0ebf603c data-v-4722a3ae><div class="community-ctrl-btns" data-v-0ebf603c><div class="community-ctrl-btns_item" data-v-0ebf603c><div data-v-160be461 data-v-0ebf603c><div data-report-click="{"spm":"3001.5975"}" data-v-160be461><img src="https://csdnimg.cn/release/cmsfe/public/img/topic.427195d5.png" alt="" class="img sendTopic" data-v-160be461 data-v-0ebf603c> <span data-v-160be461 data-v-0ebf603c>发帖</span></div> <!----> <!----></div></div><div class="community-ctrl-btns_item" data-v-0ebf603c><div data-v-0ebf603c><img src="https://csdnimg.cn/release/cmsfe/public/img/me.40a70ab0.png" alt="" class="img me" data-v-0ebf603c> <span data-v-0ebf603c>与我相关</span></div></div><div class="community-ctrl-btns_item" data-v-0ebf603c><div data-v-0ebf603c><img src="https://csdnimg.cn/release/cmsfe/public/img/task.87b52881.png" alt="" class="img task" data-v-0ebf603c> <span data-v-0ebf603c>我的任务</span></div></div><div class="community-ctrl-btns_item" data-v-0ebf603c><div class="community-share" data-v-4ca34db9 data-v-0ebf603c><div class="handle-item share" data-v-ca030a68 data-v-4ca34db9><span height="384" data-v-ca030a68><div role="tooltip" id="el-popover-2527" aria-hidden="true" class="el-popover el-popper popo share-popover" style="width:265px;display:none;"><!----><div id="tool-QRcode" class="QRcode" data-v-ca030a68><img src="https://csdnimg.cn/release/cmsfe/public/img/shareBg3.9519d347.png" alt="" class="share-bg" data-v-ca030a68> <div class="share-bg-box" data-v-ca030a68><div class="share-content" data-v-ca030a68><img src="https://img-community.csdnimg.cn/avatar/745f64491f2744dcbce3cd7127270b93.png?x-oss-process=image/resize,m_fixed,h_88,w_88" alt="" class="share-avatar" data-v-ca030a68> <div class="share-tit" data-v-ca030a68>.NET社区</div> <div class="share-dec" data-v-ca030a68>.NET技术交流专区</div> <span class="copy-share-url" data-v-ca030a68>复制链接</span> <div class="shareText" data-v-ca030a68> </div></div> <div class="share-code" data-v-ca030a68><div class="qrcode" data-v-ca030a68></div> <div class="share-code-text" data-v-ca030a68>扫一扫</div></div></div></div> </div><span class="el-popover__reference-wrapper"><div data-v-0ebf603c><img src="https://csdnimg.cn/release/cmsfe/public/img/share-circle.3e0b7822.png" alt="" class="img share" data-v-0ebf603c> <span data-v-0ebf603c>分享</span></div></span></span></div> <!----></div></div></div> <!----> <div data-v-4fb59baf data-v-0ebf603c><div class="el-dialog__wrapper ccloud-pop-outer2" style="display:none;" data-v-4fb59baf><div role="dialog" aria-modal="true" aria-label="dialog" class="el-dialog el-dialog--center" style="margin-top:15vh;width:70%;"><div class="el-dialog__header"><span class="el-dialog__title"></span><!----></div><!----><div class="el-dialog__footer"><span class="dialog-footer clearfix" data-v-4fb59baf><div class="confirm-btm fr" data-v-4fb59baf>确定</div></span></div></div></div></div></div></div></div> <div style="display:none;" data-v-4722a3ae data-v-4722a3ae><!----> <div class="introduce-desc" data-v-4722a3ae><div class="introduce-desc-title" data-v-4722a3ae>社区描述</div> <span data-v-4722a3ae> .NET技术交流专区 </span></div></div> <div class="introduce-text" data-v-4722a3ae><div class="label-box" data-v-4722a3ae><span class="label" data-v-4722a3ae>javascript</span><span class="label" data-v-4722a3ae>云原生</span> <span class="label" data-v-4722a3ae>企业社区</span> <!----></div></div> <!----> <div class="manage" data-v-4722a3ae><div class="manage-inner" data-v-4722a3ae><span data-v-4722a3ae>社区管理员</span> <ul data-v-4722a3ae><li data-v-4722a3ae><a href="https://blog.csdn.net/community_93" target="_blank" class="start-img" data-v-4722a3ae><img src="https://profile-avatar.csdnimg.cn/default.jpg!1" alt="ASP.NET" class="el-tooltip item" data-v-4722a3ae data-v-4722a3ae></a></li><li data-v-4722a3ae><a href="https://blog.csdn.net/dotnetconf" target="_blank" class="start-img" data-v-4722a3ae><img src="https://profile-avatar.csdnimg.cn/default.jpg!1" alt=".Net开发者社区" class="el-tooltip item" data-v-4722a3ae data-v-4722a3ae></a></li><li data-v-4722a3ae><a href="https://blog.csdn.net/weixin_41960540" target="_blank" class="start-img" data-v-4722a3ae><img src="https://profile-avatar.csdnimg.cn/aa17748a52c84d88ba031f9895a4ea32_weixin_41960540.jpg!1" alt="R小R" class="el-tooltip item" data-v-4722a3ae data-v-4722a3ae></a></li></ul></div></div> <div class="actions" data-v-4722a3ae><!----> <div style="flex:1;" data-v-4722a3ae><div class="join-btn" data-v-4722a3ae> 加入社区 </div></div> <!----> <!----></div> <div class="el-dialog__wrapper" style="display:none;" data-v-38c57799 data-v-4722a3ae><div role="dialog" aria-modal="true" aria-label="获取链接或二维码" class="el-dialog join-qrcode-dialog" style="margin-top:15vh;width:600px;"><div class="el-dialog__header"><span class="el-dialog__title">获取链接或二维码</span><button type="button" aria-label="Close" class="el-dialog__headerbtn"><i class="el-dialog__close el-icon el-icon-close"></i></button></div><!----><div class="el-dialog__footer"><span class="dialog-footer" data-v-38c57799></span></div></div></div> <div class="collapse-btn" data-v-4722a3ae><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAgCAYAAACFM/9sAAAAAXNSR0IArs4c6QAAAi1JREFUaEPtl01u01AUhc+N8wMSO4AxzJAqwQpKQsdtbMOICmKnwCKQ2ACDIgotrYKiduIiVZ10B0CBAjtAbICfooomJr3IcUoTiVLb15GNuG/67nm65/M5AxP0iAiQSK1iKEBhCBSgAhQSEMo1gQpQSEAo1wQqQCEBoVwT+K8CnLnWvER8cOHMaf95q9Xaj+vDtp3LPeD83u6p9a2t+U5cfVrzmSTQNOfOgg4+ATDAeNHp/Jza3Fz5HtWUZbl3GXjYn2e+53lL96Nq057LBOD0dOOcUSx8BFAcGHpZLlWmVlfnd08yaJrubRAe/Z77HwEG5kdS1E8StgFc9bzFb8dBrNtukxgLwOAXNEF6T/pAce8zSeDhknXbuUNMQRUHe/BrMNX+BNGyHIdBT45m6VVn36/FqX5cOFHmMwUYJrE5x+CgkuEujLe+361ubLS+HhowzeYtEC8NzWyXy5ValMpHgSCZyRxgsLxpui4Ij4/ShZ1S0aiurS18sSznJoOeDt29AaP6t6pLgMTV5gJgsHTddhvEWBwC9Y6AZww8AFA4Lp1xDac9nxuAYZ37aQuqGgIbPTt+t3tluNppw0jyXq4AhnV2ZkG0PAKR8b5UMiaDSicxOU5N7gCGSXRvMLAygPgB3Jv0vOXP4wSR9O1cAgzMzFxvXDR6hYlK5cd6u93eS2pw3LrcAhy38bTeV4BCkgpQAQoJCOWaQAUoJCCUawIVoJCAUK4JVIBCAkL5L1yapyGdIBwvAAAAAElFTkSuQmCC" alt data-v-4722a3ae></div></div><!----><!----><div comp-data="[object Object]" baseInfo="[object Object]" typePage="detail" community="[object Object]" class="floor-user-right-rank" data-v-3d3affee><div class="el-tabs el-tabs--top" data-v-3d3affee><div class="el-tabs__header is-top"><div class="el-tabs__nav-wrap is-top"><div class="el-tabs__nav-scroll"><div role="tablist" class="el-tabs__nav is-top" style="transform:translateX(-0px);"><div class="el-tabs__active-bar is-top" style="width:0px;transform:translateX(0px);ms-transform:translateX(0px);webkit-transform:translateX(0px);"></div></div></div></div></div><div class="el-tabs__content"><div role="tabpanel" id="pane-integral" aria-labelledby="tab-integral" class="el-tab-pane" data-v-3d3affee></div><div role="tabpanel" aria-hidden="true" id="pane-3" aria-labelledby="tab-3" class="el-tab-pane" style="display:none;" data-v-3d3affee></div><div role="tabpanel" aria-hidden="true" id="pane-5" aria-labelledby="tab-5" class="el-tab-pane" style="display:none;" data-v-3d3affee></div><div role="tabpanel" aria-hidden="true" id="pane-6" aria-labelledby="tab-6" class="el-tab-pane" style="display:none;" data-v-3d3affee></div></div></div> <div class="floor-user-right-rank-score" data-v-608528ce data-v-3d3affee><div class="floor-user-right-rank-score-tabs" data-v-608528ce><ul data-v-608528ce><li data-v-608528ce> 近7日 </li><li data-v-608528ce> 近30日 </li><li class="active" data-v-608528ce> 至今 </li></ul></div> <div class="floor-user-right-rank-common" data-v-46cf600d data-v-608528ce><div class="rank-list" data-v-46cf600d><!----> <div class="no-data loading" data-v-46cf600d><i class="el-icon-loading" data-v-46cf600d></i> <p data-v-46cf600d>加载中</p></div> <!----> <a href="https:///DotNET/rank/list/total" target="_blank" class="show-more" data-v-46cf600d> 查看更多榜单 </a></div></div></div></div><div comp-data="[object Object]" baseInfo="[object Object]" typePage="detail" community="[object Object]" class="floor comunity-rule" data-v-3cfa4dbd><div class="title" data-v-3cfa4dbd> 社区公告 </div> <div class="contain" data-v-3cfa4dbd><div class="inner-content" data-v-3cfa4dbd><p>.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。</p> <p>希望和大家一起共同营造一个活跃、友好的社区氛围。</p> </div></div></div><div comp-data="[object Object]" baseInfo="[object Object]" typePage="detail" community="[object Object]" class="user-right-adimg empty-arr" data-v-15c6aa4f><div class="adImgs" data-v-2a6389b9 data-v-15c6aa4f><!----> <div data-v-2a6389b9><!----></div></div></div><div comp-data="[object Object]" baseInfo="[object Object]" community="[object Object]" class="content-right-recommend" data-v-0f781e88><div data-v-3798762e data-v-0f781e88><!----> <!----></div></div><div comp-data="[object Object]" baseInfo="[object Object]" typePage="detail" community="[object Object]" class="ai-entrance" data-v-eb1c454c><p data-v-eb1c454c>试试用AI创作助手写篇文章吧</p> <div class="entrance-btn-line" data-v-eb1c454c><a href="https://mp.csdn.net/edit?guide=1" target="_blank" data-report-click="{"spm":"3001.9712"}" data-report-query="spm=3001.9712" class="entrance-btn" data-v-eb1c454c>+ 用AI写文章</a></div></div></div></div></div></div></div></div></div></div></div></div></div> <div> <script type="text/javascript" src="https://g.csdnimg.cn/common/csdn-footer/csdn-footer.js" data-isfootertrack="false" defer></script> </div></div></div><script> window.__INITIAL_STATE__= {"csrf":"odqMXNmQ-l78A66djjTjQWXn36cRUhFyL4bM","origin":"http:\u002F\u002Fbbs.csdn.net","isMobile":false,"cookie":"uuid_tt_dd=10_514786570-1713920331285-159889;","ip":"3.17.128.129","pageData":{"page":{"pageId":143,"title":"社区详情","keywords":"社区详情","description":"社区详情","ext":{"isMd":"true","armsfe1":"{pid:\"dyiaei5ihw@1a348e4d05c2c78\",appType:\"web\",imgUrl:\"https:\u002F\u002Farms-retcode.aliyuncs.com\u002Fr.png?\",sendResource:true,enableLinkTrace:true,behavior:true}","redPacketCfg":"{\"presetTitle\":[\"成就一亿技术人!\",\"大吉大利\",\"节日快乐\",\"Bug Free\",\"Hello World\",\"Be Greater Than Average!!\"],\"defaultTitle\":\"成就一亿技术人!\",\"preOpenSty\":{},\"redCardSty\":{}}","blogStar":"[{\"year\":\"2021\",\"enable\":true,\"communityIds\":[3859],\"url\":\"https:\u002F\u002Fbbs.csdn.net\u002Fsummary2021\"},{\"year\":\"2022\",\"enable\":true,\"communityIds\":[3860],\"url\":\"https:\u002F\u002Fbbs.csdn.net\u002Fsummary2022\"}]","mdVersion":"https:\u002F\u002Fcsdnimg.cn\u002Frelease\u002Fmarkdown-editor\u002F1.1.0\u002Fmarkdown-editor.js","componentSortCfg":"{ \"right\":[\"ratesInfo\",\"cty-profile\",\"pub-comp\",\"user-right-introduce\",\"post-event\",\"my-mission\",\"user-recommend\",\"user-right-rank\",\"user-right-rule\",\"user-right-adimg\"] }","show_1024":"{\"enable\":false,\"useWhitelist\":false,\"whitelist\":[76215],\"home\":\"https:\u002F\u002F1111.csdn.net\u002F\",\"logo\":\"https:\u002F\u002Fimg-home.csdnimg.cn\u002Fimages\u002F20221104102741.png\",\"hideLive\":true}","iframes":"[\"3859\"]","pageCfg":"{\"disableDownloadPDF\": false,\"hideSponsor\":false}"}},"template":{"templateId":71,"templateComponentName":"ccloud-detail","title":"ccloud-detail","floorList":[{"floorId":562,"floorComponentName":"floor-user-content","title":"社区详情页","description":"社区详情页","indexOrder":3,"componentList":[{"componentName":"baseInfo","componentDataId":"cloud-detail1","componentConfigData":{},"relationType":3},{"componentName":"user-right-introduce","componentDataId":"","componentConfigData":{},"relationType":2},{"componentName":"user-recommend","componentDataId":"","componentConfigData":{},"relationType":2},{"componentName":"user-right-rank","componentDataId":"","componentConfigData":{},"relationType":2},{"componentName":"user-right-rule","componentDataId":"","componentConfigData":{},"relationType":2},{"componentName":"user-right-adimg","componentDataId":"","componentConfigData":{},"relationType":2},{"componentName":"default2014LiveRoom","componentDataId":"20221024DefaultLiveRoom","componentConfigData":{},"relationType":3}]}]},"data":{"baseInfo":{"customDomain":"","uriName":"DotNET","communityHomePage":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET","owner":{"userName":"community_93","nickName":"ASP.NET","avatarUrl":"https:\u002F\u002Fprofile-avatar.csdnimg.cn\u002Fdefault.jpg!1","position":"","companyName":""},"user":{"userRole":3,"userName":null,"nickName":null,"avatarUrl":null,"rank":null,"follow":2,"communityBase":null,"joinCollege":null,"isVIP":null},"community":{"name":".NET社区","description":".NET技术交流专区","avatarUrl":"https:\u002F\u002Fimg-community.csdnimg.cn\u002Favatar\u002F745f64491f2744dcbce3cd7127270b93.png?x-oss-process=image\u002Fresize,m_fixed,h_88,w_88","qrCode":"","createTime":"2007-09-28","communityAvatarUrl":"https:\u002F\u002Fprofile-avatar.csdnimg.cn\u002Fdefault.jpg!1","communityNotice":null,"userCount":62046,"contentCount":669049,"followersCount":49818,"communityRule":"\u003Cp\u003E.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。\u003C\u002Fp\u003E\n\n\u003Cp\u003E希望和大家一起共同营造一个活跃、友好的社区氛围。\u003C\u002Fp\u003E\n","communityId":211,"bgImage":"","hashId":"2lwpzdnk","domain":"","uriName":"DotNET","externalDisplay":1,"adBanner":{"img":"","url":"","adType":0,"adCon":null},"rightBanner":{"img":"","url":"","adType":0,"adCon":null},"tagId":null,"tagName":null,"communityType":2,"communityApplyUrl":"https:\u002F\u002Fmarketing.csdn.net\u002Fquestions\u002FQ2106040308026533763","joinType":0,"visibleType":0,"collapse":0,"topicMoveAble":0,"allowActions":{},"communityOwner":"community_93","tagNameInfo":{"provinceTag":null,"areaTag":null,"technologyTags":[{"id":190,"name":"javascript"},{"id":400064,"name":"云原生"}],"customTags":[{"id":1,"name":"企业社区"}]}},"tabList":[{"tabId":862,"tabName":"问答","tabUrl":"https:\u002F\u002Fask.csdn.net\u002Flist\u002F3\u002Ftag\u002F576","tabSwitch":1,"tabType":0,"tabContribute":0,"indexOrder":0,"iframe":true,"sortType":1},{"tabId":20680,"tabName":".NET Conf China","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":1,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=20680","iframe":false,"sortType":1},{"tabId":1370,"tabName":"全部","tabUrl":"","tabSwitch":1,"tabType":4,"tabContribute":0,"cardType":0,"indexOrder":2,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=1370","iframe":false,"sortType":1},{"tabId":420,"tabName":"招聘","tabUrl":"","tabSwitch":1,"tabType":3,"tabContribute":0,"indexOrder":3,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=420","iframe":false,"sortType":1},{"tabId":23493,"tabName":"社区公告","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":3,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=23493","iframe":false,"sortType":1},{"tabId":22149,"tabName":"寻找 .NET 技术达人","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":4,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=22149","iframe":false,"sortType":1},{"tabId":714,"tabName":".NET Framework","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":5,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=714","iframe":false,"sortType":1},{"tabId":21249,"tabName":".NET Core","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":6,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=21249","iframe":false,"sortType":1},{"tabId":21248,"tabName":"微服务","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":7,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=21248","iframe":false,"sortType":1},{"tabId":21250,"tabName":".NET5 \u002F 6","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":8,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=21250","iframe":false,"sortType":1},{"tabId":21498,"tabName":".NET技术前瞻","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":9,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=21498","iframe":false,"sortType":1},{"tabId":21500,"tabName":"VC","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":10,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=21500","iframe":false,"sortType":1},{"tabId":21499,"tabName":".NET技术其他语言","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":11,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=21499","iframe":false,"sortType":1},{"tabId":21251,"tabName":"ASP_NET","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":12,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=21251","iframe":false,"sortType":1},{"tabId":21253,"tabName":"EF","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":13,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=21253","iframe":false,"sortType":1},{"tabId":21254,"tabName":"EF Core","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":14,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=21254","iframe":false,"sortType":1},{"tabId":715,"tabName":"Web Services","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":15,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=715","iframe":false,"sortType":1},{"tabId":717,"tabName":"桌面应用","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":16,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=717","iframe":false,"sortType":1},{"tabId":716,"tabName":"VB","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":17,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=716","iframe":false,"sortType":1},{"tabId":718,"tabName":"图表区","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":18,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=718","iframe":false,"sortType":1},{"tabId":21258,"tabName":"前端","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":19,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=21258","iframe":false,"sortType":1},{"tabId":4055689,"tabName":"博文收录","tabUrl":"","tabSwitch":1,"tabType":2,"tabContribute":0,"cardType":0,"indexOrder":19,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=4055689","iframe":false,"sortType":1},{"tabId":719,"tabName":"分析与设计","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":20,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=719","iframe":false,"sortType":1},{"tabId":1638782,"tabName":"Ada助手","tabUrl":"","tabSwitch":1,"tabType":2,"tabContribute":0,"cardType":0,"indexOrder":20,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=1638782","iframe":false,"sortType":1},{"tabId":720,"tabName":"组件\u002F控件开发","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":21,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=720","iframe":false,"sortType":1},{"tabId":721,"tabName":"AppLauncher","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":22,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=721","iframe":false,"sortType":1},{"tabId":21252,"tabName":"圈内交友","tabUrl":"","tabSwitch":1,"tabType":1,"tabContribute":1,"cardType":0,"indexOrder":23,"url":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET?typeId=21252","iframe":false,"sortType":1}],"dataResource":{"mediaType":"c_cloud","subResourceType":"8_c_cloud_long_text","showType":"long_text","tabId":0,"communityName":".NET社区","communityHomePageUrl":"https:\u002F\u002Fbbs.csdn.net\u002Fforums\u002FDotNET","communityType":2,"content":{"id":"270024745","contentId":270024745,"cateId":0,"cateName":null,"url":"https:\u002F\u002Fbbs.csdn.net\u002Ftopics\u002F270024745","shareUrl":"https:\u002F\u002Fbbs.csdn.net\u002Ftopics\u002F270024745","createTime":"2008-09-22 10:55:45","updateTime":"2021-05-28 17:03:51","resourceUsername":"xierfly","best":0,"top":0,"text":null,"publishDate":"2008-09-22","lastReplyDate":"2008-09-23","type":"13","nickname":"xierfly","avatar":"https:\u002F\u002Fprofile-avatar.csdnimg.cn\u002F6fae963efe554fcfb9a96b57c9ba838b_xierfly.jpg!1","username":"xierfly","commentCount":5,"diggNum":0,"digg":false,"viewCount":83,"hit":false,"resourceSource":6,"status":10,"taskStatus":null,"expired":false,"taskCate":0,"taskAward":0,"taskExpired":null,"checkRedPacket":null,"avgScore":0,"totalScore":0,"topicTitle":"如何在netweb中让数据树形显示","insertFirst":false,"likeInfo":null,"description":"目前遇到一个问题,就是让用户的留言数据分级显示,并且,其他用户可以针对某一用户的留言再进行留言;比如: 留言者:A:文章不错哦。 留言者:B:A 你认为这文章很好吗? 留言者:C:B 你认为这文章不好吗? 差不多就是这样的格式了,请知道的朋友提供点示例或指点一下。谢绝空谈的","coverImg":"https:\u002F\u002Fimg-home.csdnimg.cn\u002Fimages\u002F20221026061946.png","content":"目前遇到一个问题,就是让用户的留言数据分级显示,并且,其他用户可以针对某一用户的留言再进行留言;比如:\u003Cbr \u002F\u003E\n \u003Cbr \u002F\u003E\n 留言者:\u003Cspan style=\"color:#FF0000;\"\u003EA\u003C\u002Fspan\u003E:文章不错哦。\u003Cbr \u002F\u003E\n 留言者:\u003Cspan style=\"color:#FF0000;\"\u003EB\u003C\u002Fspan\u003E:A 你认为这文章很好吗?\u003Cbr \u002F\u003E\n 留言者:\u003Cspan style=\"color:#FF0000;\"\u003EC\u003C\u002Fspan\u003E:B 你认为这文章不好吗?\u003Cbr \u002F\u003E\n\u003Cbr \u002F\u003E\n差不多就是这样的格式了,请知道的朋友提供点\u003Cspan style=\"color:#FF0000;\"\u003E示例\u003C\u002Fspan\u003E或指点一下。\u003Cspan style=\"color:#FF0000;\"\u003E谢绝空谈的\u003C\u002Fspan\u003E","mdContent":null,"pictures":null,"videoInfo":null,"linkInfo":null,"student":{"isCertification":false,"org":"","bala":""},"employee":{"isCertification":false,"org":"","bala":""},"userCertification":[],"dependId":"0","dependSubType":null,"videoUrl":null,"favoriteCount":0,"favoriteStatus":false,"taskType":null,"defaultScore":null,"syncAsk":false,"videoPlayLength":null},"communityUser":{"userName":"xierfly","roleId":216,"roleType":0,"roleStatus":1,"honoraryId":0,"roleName":"","honoraryName":null,"communityNickname":"","communitySignature":""},"allowPost":false,"submitHistory":[{"user":{"registerurl":"https:\u002F\u002Fg.csdnimg.cn\u002Fstatic\u002Fuser-reg-year\u002F1x\u002F17.png","avatarurl":"https:\u002F\u002Fprofile-avatar.csdnimg.cn\u002F6fae963efe554fcfb9a96b57c9ba838b_xierfly.jpg!1","nickname":"xierfly","selfdesc":"暂时不想填写,","createdate":"2007-04-14 15:33:00","days":"6220","years":"17","username":"xierfly","school":null,"company":null,"job":null},"userName":"xierfly","event":"创建了帖子","body":"2008-09-22 10:55","editId":null}],"resourceExt":{}},"contentReply":{"pageNo":1,"pageSize":20,"totalPages":1,"totalCount":5,"total":0,"list":[{"hit":null,"hitMsg":null,"content":"动态输出HTML代码,根据条件在HTML中加入空格,这个方法应该可以吧,个人的想法,不过应该有更好的方法","topicTitle":null,"description":"动态输出HTML代码,根据条件在HTML中加入空格,这个方法应该可以吧,个人的想法,不过应该有更好的方法","id":240289266,"contentResourceId":270024745,"bindContentResourceId":0,"communityId":211,"username":"mengxj85","userNickName":"mengxj85","userAvatar":"https:\u002F\u002Fprofile-avatar.csdnimg.cn\u002F9d19442b816e40648f60edc6aa679f57_mengxj85.jpg!1","mdContent":null,"parentId":0,"replyName":"","replyNickName":"","bizNo":"bbs","ip":3664273542,"status":10,"childCount":0,"topStatus":0,"recommendStatus":0,"userLike":false,"diggCount":0,"childIds":"","createTime":"2008-09-23 12:51:37","updateTime":"2008-09-23 12:51:36","formatTime":"2008-09-23","userRoleHonorary":{"userName":"mengxj85","roleId":216,"roleType":0,"roleStatus":1,"honoraryId":0,"roleName":"","honoraryName":null,"communityNickname":"","communitySignature":""},"child":null,"communityNickname":null,"communityReplyNickname":null,"rewardInfo":null,"checkRedPacketVO":null,"noDiggCount":null},{"hit":null,"hitMsg":null,"content":"其实1楼的小姐说的是又道理,不过只是点水蜻蜓,需要你自己去体会延伸概念的!\u003Cbr \u002F\u003E\n1.我觉得可以动态控制HTML中的TABLE,你可以给每行的的TR做标记,当然这是为下面的留言做铺垫以及是哪个的留言,可以用AJAX实现无刷新更好看。\u003Cbr \u002F\u003E\n2.你要的要求都是可以实现的,每个留言错位,其实只是在前面加一个固定长度的一列,就是1楼小姐说的空格,根据你发表的,在后台处理代码发回HTML段,控制TR减少还增加是可行的!\u003Cbr \u002F\u003E\n3.以上的要求你必须知道AJAX和Table的详细操作,网上又很多列子!\u003Cbr \u002F\u003E\n最终个人结论:这个很简单,因为有合理的逻辑就是可以做出来的!","topicTitle":null,"description":"其实1楼的小姐说的是又道理,不过只是点水蜻蜓,需要你自己去体会延伸概念的! 1.我觉得可以动态控制HTML中的TABLE,你可以给每行的的TR做标记,当然这是为下面的留言做铺垫以及是哪个的留言,可以用AJAX实现无刷新更好看。 2.你要的要求都是可以实现的,每个留言错位,其实只是在前面加一个固定长度的一列,就是1楼小姐说的空格,根据你发表的,在后台处理代码发回HTML段,控制TR减少还增加是可行的! 3.以上的要求你必须知道AJAX和Table的详细操作,网上又很多列子! 最终个人结论:这个很简","id":240291362,"contentResourceId":270024745,"bindContentResourceId":0,"communityId":211,"username":"lfywy","userNickName":"lfywy","userAvatar":"https:\u002F\u002Fprofile-avatar.csdnimg.cn\u002Fac791ce4cd62401d82f8fcbce900b599_lfywy.jpg!1","mdContent":null,"parentId":0,"replyName":"","replyNickName":"","bizNo":"bbs","ip":3524696990,"status":10,"childCount":0,"topStatus":0,"recommendStatus":0,"userLike":false,"diggCount":0,"childIds":"","createTime":"2008-09-23 09:15:42","updateTime":"2008-09-23 09:15:47","formatTime":"2008-09-23","userRoleHonorary":{"userName":"lfywy","roleId":216,"roleType":0,"roleStatus":1,"honoraryId":0,"roleName":"","honoraryName":null,"communityNickname":"","communitySignature":""},"child":null,"communityNickname":null,"communityReplyNickname":null,"rewardInfo":null,"checkRedPacketVO":null,"noDiggCount":null},{"hit":null,"hitMsg":null,"content":"A的留言:1000\u003Cbr \u002F\u003E\nB给A的留言:10001000\u003Cbr \u002F\u003E\nC给A的留言:10001001\u003Cbr \u002F\u003E\nD的留言:1001","topicTitle":null,"description":"A的留言:1000 B给A的留言:10001000 C给A的留言:10001001 D的留言:1001","id":240291274,"contentResourceId":270024745,"bindContentResourceId":0,"communityId":211,"username":"wolfsky1994","userNickName":"wolfsky1994","userAvatar":"https:\u002F\u002Fprofile-avatar.csdnimg.cn\u002Fdefault.jpg!1","mdContent":null,"parentId":0,"replyName":"","replyNickName":"","bizNo":"bbs","ip":2111013750,"status":10,"childCount":0,"topStatus":0,"recommendStatus":0,"userLike":false,"diggCount":0,"childIds":"","createTime":"2008-09-23 09:12:20","updateTime":"2008-09-23 09:12:20","formatTime":"2008-09-23","userRoleHonorary":{"userName":null,"roleId":null,"roleType":null,"roleStatus":null,"honoraryId":null,"roleName":null,"honoraryName":null,"communityNickname":null,"communitySignature":null},"child":null,"communityNickname":null,"communityReplyNickname":null,"rewardInfo":null,"checkRedPacketVO":null,"noDiggCount":null},{"hit":null,"hitMsg":null,"content":"数据库设计的时候加入分级的字段设计\u003Cbr \u002F\u003E\n1000\u003Cbr \u002F\u003E\n10001000\u003Cbr \u002F\u003E\n10001001\u003Cbr \u002F\u003E\n100010001001\u003Cbr \u002F\u003E\n1001\u003Cbr \u002F\u003E\n根据层次的定义控制输入和输出","topicTitle":null,"description":"数据库设计的时候加入分级的字段设计 1000 10001000 10001001 100010001001 1001 根据层次的定义控制输入和输出","id":240291227,"contentResourceId":270024745,"bindContentResourceId":0,"communityId":211,"username":"wolfsky1994","userNickName":"wolfsky1994","userAvatar":"https:\u002F\u002Fprofile-avatar.csdnimg.cn\u002Fdefault.jpg!1","mdContent":null,"parentId":0,"replyName":"","replyNickName":"","bizNo":"bbs","ip":2111013750,"status":10,"childCount":0,"topStatus":0,"recommendStatus":0,"userLike":false,"diggCount":0,"childIds":"","createTime":"2008-09-23 09:11:12","updateTime":"2008-09-23 09:11:12","formatTime":"2008-09-23","userRoleHonorary":{"userName":null,"roleId":null,"roleType":null,"roleStatus":null,"honoraryId":null,"roleName":null,"honoraryName":null,"communityNickname":null,"communitySignature":null},"child":null,"communityNickname":null,"communityReplyNickname":null,"rewardInfo":null,"checkRedPacketVO":null,"noDiggCount":null},{"hit":null,"hitMsg":null,"content":"谢谢楼上的朋友,\u003Cbr \u002F\u003E\n但是我要的不是说空格的问题,而是让留言有层次感,可以对留言者说的话再进行留言。","topicTitle":null,"description":"谢谢楼上的朋友, 但是我要的不是说空格的问题,而是让留言有层次感,可以对留言者说的话再进行留言。","id":240290588,"contentResourceId":270024745,"bindContentResourceId":0,"communityId":211,"username":"xierfly","userNickName":"xierfly","userAvatar":"https:\u002F\u002Fprofile-avatar.csdnimg.cn\u002F6fae963efe554fcfb9a96b57c9ba838b_xierfly.jpg!1","mdContent":null,"parentId":0,"replyName":"","replyNickName":"","bizNo":"bbs","ip":1033139250,"status":10,"childCount":0,"topStatus":0,"recommendStatus":0,"userLike":false,"diggCount":0,"childIds":"","createTime":"2008-09-23 08:51:24","updateTime":"2008-09-23 08:51:24","formatTime":"2008-09-23","userRoleHonorary":{"userName":"xierfly","roleId":216,"roleType":0,"roleStatus":1,"honoraryId":0,"roleName":"","honoraryName":null,"communityNickname":"","communitySignature":""},"child":null,"communityNickname":null,"communityReplyNickname":null,"rewardInfo":null,"checkRedPacketVO":null,"noDiggCount":null}],"maxPageSize":3000},"defaultActiveTab":20680,"recommends":[{"url":"https:\u002F\u002Fdownload.csdn.net\u002Fdownload\u002Fu013960699\u002F11312424","title":"Tree_Demo.rar","desc":"日常在\u003Cem\u003EWeb\u003C\u002Fem\u003E项目开发时,经常会碰到\u003Cem\u003E树形\u003C\u002Fem\u003E架构\u003Cem\u003E数据\u003C\u002Fem\u003E的\u003Cem\u003E显示\u003C\u002Fem\u003E,从\u003Cem\u003E数据\u003C\u002Fem\u003E库\u003Cem\u003E中\u003C\u002Fem\u003E获取\u003Cem\u003E数据\u003C\u002Fem\u003E,并且\u003Cem\u003E显示\u003C\u002Fem\u003E成\u003Cem\u003E树形\u003C\u002Fem\u003E。为了方便,我们可以写一个javascript的一个跨浏览器树控件,后续可以重复使用。本节分享一个自己开发的JS tree插件,对有需要的朋友可以直接下载使用。\n\n Tree插件 需要实现\n\n (1)、自动将\u003Cem\u003E数据\u003C\u002Fem\u003E组织成上下级关系,这样我们在前端手工添加\u003Cem\u003E数据\u003C\u002Fem\u003E或者从\u003Cem\u003E数据\u003C\u002Fem\u003E库\u003Cem\u003E中\u003C\u002Fem\u003E获取到的\u003Cem\u003E数据\u003C\u002Fem\u003E不需要我们来组织上下级关系\n\n (2)、支持自定 加载目录树 支持XML、JSON 格式的\u003Cem\u003E数据\u003C\u002Fem\u003E加载\n\n (3)、实现树节点的选择(单选、复选[级联选择])功能\n\n (4)、支持大\u003Cem\u003E数据\u003C\u002Fem\u003E的一次性加载","createTime":"2019-07-10 10:51:25","dataReportQuery":"spm=1035.2023.3001.6557&utm_medium=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Paid-1-11312424-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default&depth_1-utm_source=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Paid-1-11312424-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default","dataReportClick":"{\"mod\":\"popu_645\",\"index\":\"1\",\"dest\":\"https:\u002F\u002Fdownload.csdn.net\u002Fdownload\u002Fu013960699\u002F11312424\",\"strategy\":\"2~default~OPENSEARCH~Paid\",\"extra\":\"{\\\"utm_medium\\\":\\\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Paid-1-11312424-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\\\",\\\"dist_request_id\\\":\\\"1713920331325_95453\\\"}\",\"spm\":\"1035.2023.3001.6557\"}","dataReportView":"{\"mod\":\"popu_645\",\"index\":\"1\",\"dest\":\"https:\u002F\u002Fdownload.csdn.net\u002Fdownload\u002Fu013960699\u002F11312424\",\"strategy\":\"2~default~OPENSEARCH~Paid\",\"extra\":\"{\\\"utm_medium\\\":\\\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Paid-1-11312424-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\\\",\\\"dist_request_id\\\":\\\"1713920331325_95453\\\"}\",\"spm\":\"1035.2023.3001.6557\"}","type":"download"},{"url":"https:\u002F\u002Fdownload.csdn.net\u002Fdownload\u002Fsuper_zhaowenke\u002F2190657","title":"ExtAspNet v2.2.1 (2009-4-1) 值得一看","desc":"ExtAspNet v2.2.1\n\t\nExtAspNet是一组专业的Asp.net控件库,拥有原生的AJAX支持和丰富的UI效果,\n目标是创建没有JavaScript,没有CSS,没有UpdatePanel,没有\u003Cem\u003EWeb\u003C\u002Fem\u003EServices的\u003Cem\u003EWeb\u003C\u002Fem\u003E应用程序。\n\n支持的浏览器: IE 7.0+, Firefox 3.0+, Chrome 2.0+, Opera 9.5+, Safari 3.0+\n\n注:ExtAspNet基于一些开源的程序ExtJS, HtmlAgilityPack, Nii.JSON, YUICompressor。\n\n示例: http:\u002F\u002Fextasp.net\u002F\n开源: http:\u002F\u002Fextaspnet.codeplex.com\u002F\n博客: http:\u002F\u002Fsanshi.cnblogs.com\u002F\n邮箱: sanshi.ustc@gmail.com\n\n\n发布历史:\n\n+2010-03-28 v2.2.1\n\t+为TabStrip的GetAddTabReference函数增加重载方法,以便指定Tab的图标(feedback:mmdcup)。 \n\t\t-修正此函数通过PageContext.RegisterStartupScript调用时不能正确\u003Cem\u003E显示\u003C\u002Fem\u003EIcon的BUG(feedback:zhaowenke)。\n\t-修正basic\u002Fhello.aspx示例在单独浏览器打开后,不能弹出对话框的BUG。\n\t-隐藏示例首页最外层RegionPanel的边框ShowBorder=\"false\"。\n\t+集成Extjs最新版本v3.1.1。\n\t\t-增加一个新的Theme - Access。\n\t\t-修正了Firefox下Zoom In\u002FOut时页面消失的BUG。\n\t\t-删除Panel的EnableLightBackgroundColor属性,同时EnableBackgroundColor只支持Blue和Gray两种Theme。\n\n\n\n+2010-01-31 v2.2.0\n\t-使得Asp.net的控件ImageButton具有和Asp.net的Button控件类似的行为(Ajax提交)(feedback:261629698)。\n\t+TabStrip增加GetAddTabReference和GetRemoveTabReference两个函数,用来向TabStrip控件动态增加删除Tab。\n\t\t-增加示例tabstrip\u002Ftabstrip_addtab.aspx。\n\t-重构了示例网站的架构,目前只有一层IFrame结构。\n\t-为TabStrip增加EnableTabCloseMenu属性,是否启用右键菜单,可用来关闭当前Tab和所有其他Tab。\n\t-为NumberBox增加DecimalPrecision属性,用来控制小数点后的位数(需要设置NoDecimal=\"false\")(feedback:zqmars)。\n\t-Window控件更新。\n\t\t-关闭按钮默认直接关闭,不会弹出确认对话框。\n\t\t-GetConfirmFormModifiedHideReference的函数\u003Cem\u003E中\u003C\u002Fem\u003E的ConfirmFormModified简化为Confirm,所以此函数更名为GetConfirmHideReference。\n\t\t-增加两个属性EnableConfirmOnClose(默认false),CloseAction(Hide, HideRefresh, HidePostBack)。\n\t\t-修正EnableMaximize属性不能使Window最大化的BUG,修正了双击标题栏不能最大化的BUG。\n\t-删除Button控件的SystemIcon属性,比如以前这样定义SystemIcon=\"Close\",现在需要这样定义Icon=\"SystemClose\"。\n\t-WindowPosition默认居\u003Cem\u003E中\u003C\u002Fem\u003E,而不是黄金分割位置。\n\t+Button, Window等控件弹出位置属性的变化。\n\t\t-Window的Target属性由字符串类型变为枚举类型,注意更新以前的代码:Target=\"_self\" -\u003E Target=\"Self\", Target=\"_parent\" -\u003E Target=\"Parent\"。\n\t\t-MenuButton, LinkButton, Button, LinkButtonField的ConfirmTarget属性由字符串变为枚举类型,可以取三个枚举值Self, Parent, Top。\n\t\t-Confirm.GetShowReference的最后一个参数target变为枚举类型。\n\t\t-Alert.GetShowReference\u003Cem\u003E中\u003C\u002Fem\u003E的showInParent参数也变为Target枚举类型。\n\t\t-MenuButton, LinkButton, Button, LinkButtonField增加ValidateTarget用来控制表单验证失败时提示对话框的\u003Cem\u003E显示\u003C\u002Fem\u003E位置。\n\n\n\n+2010-01-06 v2.1.9\n\t-集成Extjs最新版本v3.1.0。\n\t-修正灰色皮肤的CSS问题。\n\t-修正Grid的列名\u003Cem\u003E中\u003C\u002Fem\u003E不能包含\u003Cem\u003E中\u003C\u002Fem\u003E文字符的BUG(feedback:davidwen)。\n\t-为\u003Cem\u003EWeb\u003C\u002Fem\u003E.config和PageManager增加属性AjaxTimeout(单位秒,默认30秒)。\n\t-修正了在Grid的PageIndexChange事件\u003Cem\u003E中\u003C\u002Fem\u003E不能获取SelectedRowIndexArray属性的BUG(feedback:Violet)。\n\t-Button控件将不再自动拥有display:inline属性,如果希望两个按钮在一行\u003Cem\u003E显示\u003C\u002Fem\u003E,请为第一个按钮设置CssStyle=\"float:left;\"属性。\n\t-修正了弹出菜单的位置在Firefox下不正确的BUG(feedback:eroach)。\n\t-为TriggerBox和TwinTriggerBox增加EnableEdit属性。\n\t-使用Hidden来\u003Cem\u003E显示\u003C\u002Fem\u003E隐藏ExtAspNet控件,而不是使用Visible属性(Visible目前设置为只读属性)。\n\t-使用Hidden控制Window控件的\u003Cem\u003E显示\u003C\u002Fem\u003E隐藏,Popup已经标记为Obsolete属性。\n\t-Window的实例方法GetCloseReference等以及ActiveWindow的静态方法GetCloseReference等,其\u003Cem\u003E中\u003C\u002Fem\u003E的Close全部改为Hide。\n\t-增加TabStrip\u003Cem\u003E中\u003C\u002Fem\u003ETab控件可关闭属性EnableClose(默认为false)以及两个方法GetShowReference和GetHideReference(feedback:anson)。\n\t-修正绑定到Tree的XMLDocument\u003Cem\u003E中\u003C\u002Fem\u003EIcon属性映射错误(feedback:nopnop9)。\n\t-修正HtmlEditor不能编辑的BUG(feedback:TheBox)。\n\t-修正IE下有时会出现空白页面的情况(feedback:olivia919)。\n\t\n\t\n\n+2009-12-06 v2.1.8\n\t-修正了使用IFrame的Window关闭后不能再次打开的BUG(feedback:alexa99)。\n\t-修正了IE下Grid\u003Cem\u003E中\u003C\u002Fem\u003E的一个JS问题(feedback:lqm4108)。\n\t-修正Alert消息\u003Cem\u003E中\u003C\u002Fem\u003E引号未编码导致的JS错误(feedback:sun1299shine)。\n\t+集成extjs3.0.3。\n\t\t-修正弹出对话框的宽度计算错误(会保持最小的状态)。\n\t\t-增加新的皮肤Gray。\n\t-为示例工程添加改变语言和皮肤的下拉列表。\n\t-为PageContext增加静态函数Refresh,在切换语言和皮肤时使用。\t\n\n\n\n+2009-12-01 v2.1.7\n\t-增加示例(iframe\u002Fparent_postback_run3.aspx),如何通过简单的Javascript代码回发父页面(feedback:eroach)。\n\t-修正一些书写错误(feedback:bmck)。\n\t-从Region控件\u003Cem\u003E中\u003C\u002Fem\u003E删除SplitColor属性,增加CollapseMode, EnableSplitTip, SplitTip, CollapsibleSplitTip属性(feedback:bmck)。\n\t-BorderPanel更名为RegionPanel。\n\t-DropDownList拥有MarkInvalid方法(feedback:sun1299shine)。\n\t-增加\u003Cem\u003E中\u003C\u002Fem\u003E国的省市县三级联动示例(data\u002Fshengshixian.aspx)(feedback:Blues T)。\n\t-修正了使用IFrameUrl的Tab在切换过程\u003Cem\u003E中\u003C\u002Fem\u003E会重复加载的问题,这是一个在v2.1.6引入的问题(feedback:eroach)。\n\t-修正了启用AutoPostBack的Grid,其RowClick会覆盖LinkButtonField, HyperLinkField, CheckBoxField的点击事件(feedback:yymaoji)。\n\t\n\t\n\t\n+2009-11-26 v2.1.6\n\t+修正动态创建Grid列的BUG(feedback:gxpan)。\n\t\t-增加示例(data\u002Fgrid_dynamic_columns.aspx)。\n\t-修正Form不能自适应浏览器大小的改变(feedback:kaywood)(WorkItem#6309)。\n\t-增加重载方法Alert.Show(message, title, icon)(feedback:TheBox)(WorkItem#6353)。\n\t-为容器控件(比如Panel,Region,Tab等)增加AJAX属性IFrameUrl(feedback:BluesT)。\n\t-重新设计模拟树的下拉列表的实现,避免选\u003Cem\u003E中\u003C\u002Fem\u003E某项后的闪烁。\n\t\t\t\n\n\n+2009-11-21 v2.1.5\n\t+Tree优化。\n\t\t-修正Expanded项和Checked项的状态在回发改变后不能保持的BUG。\n\t\t-GetNodeById更名为FindNode,保持和FindControl一致命名。\n\t\t-删除CheckedNodeIDArray属性,增加GetCheckedNodes和GetCheckedNodeIDs函数。\n\t\t-删除ExpandedNodeIDArray属性,增加GetExpandedNodes和GetExpandedNodeIDs函数。\n\t\t-增加示例(data\u002Ftree_select_run.aspx),如何选\u003Cem\u003E中\u003C\u002Fem\u003E当前节点的所有子节点(feedback:wjl_wjl520)。\n\t\t+TreeNode的属性NodeId被重命名为NodeID,这是ExtAspNet\u003Cem\u003E中\u003C\u002Fem\u003E的一个命名约定。\n\t\t\t-同时更名的还有GridColumn的ColumnId-\u003EColumnID,GetColumnId-\u003EGetColumnID。\n\t\t\t-Grid1.Columns.FindColumnById函数被Grid1.FindColumn所替代。\n\t\t-为TreeCheckEventArgs,TreeExpandEventArgs,TreeCommandEventArgs增加Node属性。\n\t-为所有控件增加Focus(覆盖Control默认的Focus函数)和GetFocusReference函数。\n\t-增加示例(other\u002Fcustom_postback.aspx)(feedback:thebox)。\n\t\t-如何自定义Javascript脚本和C#处理函数来响应键盘事件。\n\t-为Tree增加AutoLeafIdentification属性。\n\t\t-增加示例(tree_auto_leaf_identification.aspx)(feedback:wdrabbit)。\n\t\n\t\n\n+2009-11-17 v2.1.4\n\t-修正Window的关闭按钮提示信息一直是\u003Cem\u003E中\u003C\u002Fem\u003E文的BUG(feedback:thebox)。\n\t-部分ExtAspNet控件的设计时支持(会在后续版本\u003Cem\u003E中\u003C\u002Fem\u003E逐步完善)。\n\t-v0.2beta2版本\u003Cem\u003E中\u003C\u002Fem\u003E关于PersistChildren(true)的描述有误,这个是设计时属性,和运行时是否保持状态没有关系。\n\t-修正CheckBox控件的CheckedChanged事件会被触发两次的BUG(Data PostBack-\u003EAutoPostBack, Event PostBack-\u003EEnablePostBack)。\n\t-为TextBox,TextArea,DatePicker,NumberBox,TriggerBox等控件增加AutoPostBack属性(feedback:dk3214)。\n\t+为表单字段增加RequiredMessage,MaxLengthMessage,MinLengthMessage属性,用于指定验证失败时提示信息。\n\t\t-为空则使用默认的提示信息,默认的提示信息支持多语言,建议一般情况下使用默认信息。\n\t+为表单字段增加MarkInvalid和GetMarkInvalidReference函数(feedback:sun1299shine)。\n\t\t-增加示例:form\u002Fform_validate.aspx\n\t\n\t\n\n+2009-10-19 v2.1.3\n\t+增加支持在AJAX时改变的控件属性列表(\u002Fajax.aspx)。\n\t\t-ExtAspNet支持原生的AJAX,也就是说控件的属性改变在AJAX过程\u003Cem\u003E中\u003C\u002Fem\u003E会反映到页面\u003Cem\u003E中\u003C\u002Fem\u003E,但并不是所有的控件属性都支持AJAX改变。\n\t-加载s.gif图片在本机进行,不会请求extjs.com远程资源(feedback:efrigate43,abaocoole)。\n\t-在AJAX回发后确保Asp.net的按钮控件仍然具有AJAX的特性。\n\t-更新\u002Fbasic\u002Flogin.aspx示例,使用验证图片(feedback:kedee)。\n\t-为Grid增加AutoPostBack属性和RowClick事件,示例在\u002Fdata\u002Fgrid_autopostback.aspx(feedback:chenguizhu2006)。\n\t-为所有的表单字段增加AJAX属性ReadOnly(feedback:skydb)。\n\t-Grid\u003Cem\u003E中\u003C\u002Fem\u003ETemplateField生成到页面\u003Cem\u003E中\u003C\u002Fem\u003E控件具有唯一ID,例如Grid1_ct5_Label2,Grid1_ct6_Label2(feedback:geruger)。\n\t\n\t\n\n+2009-09-27 v2.1.2\n\t-为Tree控件增加GetExpandAllNodesReference和GetCollapseAllNodesReference两个函数。\n\t-修正RELEASE版本下多语言加载的BUG(feedback:yigehaoren)。\n\t-增加pt_BR语言,由Ujvari提供。\n\t+为所有Panel(包括Grid,Tree,Form等)增加枚举类型Icon,其\u003Cem\u003E中\u003C\u002Fem\u003E包含1700多个小图标。\n\t\t-如果Panel具有IconUrl属性,则IconUrl优先于Icon。\n\t\t-所有Icon的列表在icon.aspx。\n\t-为Button,MenuItem(MenuButton,MenuHyperLink),AccordionLink,TreeNode,Image(如果ImageUrl为空,则取Icon的值)增加Icon属性。\n\t\n\t\n\n+2009-09-15 v2.1.1\n\t-修正不能动态修改AccordionPane属性Items的BUG。\n\t+为Button, MenuButton, LinkButton, LinkButtonField增加ConfirmTarget。\n\t\t-如果需要在父页面弹出确认对话框,需要设置ConfirmTarget=\"_parent\"(类似Window控件的Target=\"_parent\")。\n\t+为ExtAspNet.Alert.Show增加点击确定的JavaScript回调函数。\n\t\t-一个典型应用,在Window控件\u003Cem\u003E中\u003C\u002Fem\u003E打开新页面,如果传递的参数不正确,则首先提示参数不对然后关闭此弹出窗口。\n\t\t-ExtAspNet.Alert.Show(\"参数错误!\", String.Empty, ExtAspNet.ActiveWindow.GetCloseReference());\n\t+TreeNode的前面的多选框可以自动回发了。\n\t\t-为TreeNode增加AutoPostBack属性,增加事件\u003Cem\u003E数据\u003C\u002Fem\u003E类TreeCheckEventArgs,为Tree增加事件NodeCheck。\n\t\t-示例在:http:\u002F\u002Fextasp.net\u002Fdata\u002Ftree_run.aspx\n\t-Grid增加GetNoSelectionAlertInParentReference函数,用来表示没有选\u003Cem\u003E中\u003C\u002Fem\u003E任何一项时在父页面弹出对话框的JS代码。\n\t-修正IE7下不能以下划线作为CSS\u003Cem\u003E中\u003C\u002Fem\u003E类名的前缀的BUG(feedback:Steve.Wei)。\n\t-添加定时器控件Timer,用来定时发起AJAX请求。\n\t\n\t\n\n+2009-09-06 v2.1.0\n\t-Button的Pressed属性值能够正确的反映客户端的变化。\n\t-优化Tree控件的AJAX实现。\n\t+为页面的Form添加autocomplete=\"off\"属性。\n\t\t-参考http:\u002F\u002Fwww.cnblogs.com\u002Fsanshi\u002Farchive\u002F2009\u002F09\u002F04\u002F1560146.html#1635830\n\t+添加对extjs3.0\u003Cem\u003E中\u003C\u002Fem\u003E所有语言的支持。\n\t\t-ExtAspNet扩展的多语言包在js\\languages\\extaspnet目录下,目前只有en,zh_CN,zh_TW三种实现\n\t\t-你可以向其\u003Cem\u003E中\u003C\u002Fem\u003E添加自己的语言版本,并执行js\\languages下的pack.bat打包,最后编译工程。\n\t\n\t\n\t\n+2009-09-01 v2.0.9\n\t-为ExtAspNet.Alert添加两个静态方法ShowInParent和GetShowInParentReference,用于在父页面弹出窗口。\n\t+在aspx页面\u003Cem\u003E中\u003C\u002Fem\u003E必须\u003Cem\u003E显示\u003C\u002Fem\u003E的声明控件的集合属性(比如Tabs(TabStrip), Items(PanelBase), Nodes(TreeNode))。\n\t\t-这将会影响所有的aspx页面,所以要特别关注。\n\t-重命名AccordionPanel为AccordionPane (这也是在Asp.net AJAX\u003Cem\u003E中\u003C\u002Fem\u003E使用的名称).\n\t+所有的面板默认有两个集合属性(Toolbars和Items).\n\t\t-尽管TabStrip, From, Tree, Accordion继承了Items属性,但是你并不能对其设置(此时Items是只读的).\n\t\t-这将会影响所有的aspx页面,一定要将工具条(Toolbars)和Items区分开来。\n\t-祝你生日快乐 - 小师妹妹。\n\n\n\n+2009-08-29 v2.0.8\n\t-ExtAspNet支持多语言(en,zh_CN,zh_TW),可以在\u003Cem\u003EWeb\u003C\u002Fem\u003E.config\u003Cem\u003E中\u003C\u002Fem\u003E修改。\n\t-将所有的示例转化为英语版本。\n\t-修正Tree控件的一个BUG(定义Mappings属性时)。\n\t+PageManager.Instance应该存在于HttpContext.Current,而不是一个全局变量。\n\t -这个BUG导致Asp.net compatibility\u003Cem\u003E中\u003C\u002Fem\u003E的示例无法完成,现在已经修正。\n\t+去除PageManager\u003Cem\u003E中\u003C\u002Fem\u003E方法AddAjaxAspnetControls,增加属性AjaxAspnetControls。\n\t -这个属性和Button得ValidateForms属性类似,可以查看Asp.net compatibility\u003Cem\u003E中\u003C\u002Fem\u003E的示例。\n\t\n\t\n\n+2009-08-25 v2.0.7\n -为按钮增加DisableControlBeforePostBack属性 - 回发之前是否禁用按钮,防止重复提交 - 默认为true。\n -Grid的Values属性访问限制由internal改为public,这就意味这可以自由改变Grid\u003Cem\u003E中\u003C\u002Fem\u003E每个单元格的值了。\n -增加示例-如何将Grid控件导出为Excel(data\\grid_excel_run.aspx)(feedback:503684912)。\n -如果TreeNode的属性Enabled=\"false\",则此项变灰并且不会被选\u003Cem\u003E中\u003C\u002Fem\u003E(feedback:your568)。\n -修正TreeNode的属性NavigateUrl不接受服务器端URL(以~\u002F开头)的BUG。\n -增加Accordion和Tree配合使用的示例(other\\accordion_tree_run.aspx)。\n -修正Panel图标不能\u003Cem\u003E显示\u003C\u002Fem\u003E的BUG(CSS\u003Cem\u003E中\u003C\u002Fem\u003Eclass名不能有$字符)。\n +去除PageLayout控件,此控件可以使用BorderLayout和指定PageManager的AutoSizePanelID属性来代替。\n\t\t-这样所有需要占据全屏的Panel(不管你是Accordion,Panel,ContentPanel,Form,GroupPanel,SimpleForm,Tree还是Grid,TabStrip)都可以通过这种方式全屏。\n\t\t-简单方便,示例可以参考 default.aspx 或者 other\\accordion_tree_run.aspx。\n \n \n\n+2009-08-14 v2.0.6\n\t-动态生成菜单实例(other\\menu_dynamic_run.aspx和other\\menu_dynamic2_run.aspx)(feedback:shguo)。\n\t-优化AJAX的内部实现,每个页面保存的ViewState现在减少1\u002F3左右(重要更新)。\n\t-优化Tree节点的NodeId自动生成,减少ViewState占用。\n\t\n\n\n+2009-08-09 v2.0 beta5\n\t+ExtAspNet和Asp.net的提交按钮兼容问题(feedback:千帆)。\n\t\t-在2009-03-03 v1.3.0曾经提到这个兼容问题,并有这样的规则,如果Asp.net的按钮AJAX提交,必须设置UseSubmitBehavior=\"false\"\n\t\t--也就是说生成的input的type不能是\"submit\",而这个限制在有些情况下是不可原谅的。\n\t\t--我们做了优化,现在要使一个Asp.net的按钮能够AJAX提交,你不需要做任何设置(PageManager的属性EnableAjax为true即可,这是默认属性)。\n\t+PageManager的实例方法AddAjaxUpdateControl改名为AddAjaxAspnetControls,现在可以在Page_Load\u003Cem\u003E中\u003C\u002Fem\u003E设置需要在AJAX\u003Cem\u003E中\u003C\u002Fem\u003E需要更新的Asp.net控件了。\n\t\t-在Page_Load\u003Cem\u003E中\u003C\u002Fem\u003E设置了哪些需要在AJAX\u003Cem\u003E中\u003C\u002Fem\u003E更新的Asp.net控件会在回发时保持状态,可以通过RemoveAjaxAspnetControls来去除不需要更新的控件。\n\t\t-示例在aspnet\\fckeditor_run.aspx和aspnet\\aspnet_run.aspx。\n\t\t-FCKEditor和上传控件兼容。示例在aspnet\\fileupload_run.aspx。\n\t-修正ToolbarText的文本在AJAX下更新的BUG。\n\t-Button的Pressed属性在AJAX可更新(feedback:mgzhenhong)。\n\t-更新所有示例。在IE7.0,IE8.0,Firefox3.5,Chrome2.0下测试通过。\n\t\n\n\n+2009-08-02 v2.0 beta4\n\t+和Asp.Net的Forms Authentication兼容[feedback:mgzhenhong]。\n\t\t-采用和Asp.Net Ajax类似的处理方式,需要在配置文件\u003Cem\u003EWeb\u003C\u002Fem\u003E.config增加一个httpModules。\n\t\t-现在支持Response.Redirect,你可以选择Response.Redirect或者ExtAspNet.PageContext.Redirect重定向页面,两者效果一样。\n\t\t-支持FormsAuthentication.RedirectFromLoginPage(accountID, false);这样的方法。\n\t-Button增加Type属性(button,reset,submit)[feedback:mgzhenhong]。\n\t-修正Alert.Show方法不能指定文本前图片的BUG[feedback:xmq&mgzhenhong]。\n\t-修正IE下某些弹出窗口的IFrame第一次不能加载的BUG。\n\t-增加Menu和Accordion的示例。\n\t-修正Window控件的IconUrl有时不\u003Cem\u003E显示\u003C\u002Fem\u003E(Target=\"_parent\")的BUG[feedback:xmq&mgzhenhong]。\n\t\n\n\n+2009-07-22 v2.0 beta3\n\t-兼容FCKEditor。\n\t-在IE8.0,Firefox3.5下测试通过。以后ExtAspNet将不会对IE6.0提供支持。\n\t\n\n\n+2009-07-13 v2.0 beta2\n\t-集成extjs最新版本v3.0。\n\t+兼容IE6.0-7.0-8.0。\n\t\t-这应该是Extjs3.0的一个BUG,在IE6.0-7.0下面设置Ext.QuickTips.init();会导致button的click事件无法响应(IE8下无此问题)。\n\t\t-目前先禁用IE6.0-7.0的QuickTips。\n\t-优化底层JavaScript。\n\t\n\t\n\t\n+2009-07-05 v2.0 beta1\n\t-更新extjs库到最新版本v3.0 RC2; 目前只有一个缺省皮肤(Theme)。\n\t-使用YUI Compressor压缩JavaScript和CSS文件。\n\t-Release版本每个页面只包含一个JavaScript文件(语言文件除外)和一个CSS文件。\n\t-ExtAspNet自身的CSS会紧挨着页面\u003Ctitle\u003E标签引入,这样在\u003Chead\u003E\u003Cem\u003E中\u003C\u002Fem\u003E自定义的样式可以覆盖ExtAspNet缺省样式。\n\t+Alert对话框会遮挡所有的Window窗口。\n\t\t-使用一个变通的方法解决,因为无法改变Ext.Message的默认z-index(9000)所以将box.window_default_group的zseed调整为6000。\t\n\t-为所有按钮的左右增加5px的空白边距:.x-btn button { margin: 0 5px !important; }。\n\t-因为下拉列表不可编辑,所以不能为空,如果不设置SelectedIndex或SelectedValue,则默认选\u003Cem\u003E中\u003C\u002Fem\u003E第一项。\n\t-重新绑定模拟树的下拉列表后,选\u003Cem\u003E中\u003C\u002Fem\u003E项的前面有图片的HTML标签的BUG。\n\t-更新自定义JavaScript组件Ext.ux.SimplePagingToolbar。\n\t-更新示例工程。\n\t\n\t\n\n+2009-03-25 v1.3.1\n\t-Tree在AJAX回发展开节点时JS错误[feedback:xlli]。[fixed]\n\t-Window\u003Cem\u003E中\u003C\u002Fem\u003E的EnableIFrame==false,则点击关闭按钮时报JS错误。[fixed]\n\t-页面包含FileUpload控件,需要点击按钮回发并上传文件,则不能采用原生AJAX方式。(参见示例aspnet\u002Ffileupload.aspx)[fixed]\n\t-HtmlEditor\u003Cem\u003E显示\u003C\u002Fem\u003E隐藏工具栏按钮不起作用,HtmlEditor目前不支持Enabled和Readonly两个属性。[fixed]\n\t\n\t\n\n+2009-03-03 v1.3.0\n\t-如果弹出的窗口(Ext-Window)含有ASP.NET控件FileUpload,则此弹出窗口在关闭时出现JS错误(http:\u002F\u002Fextjs.com\u002Fforum\u002Fshowthread.php?t=8129)[feedback:xlli]。[fixed]\n\t-如果页面\u003Cem\u003E中\u003C\u002Fem\u003E存在ASP.NET控件(TextBox),则第二次提交表单就会报错(视图状态不对,其实时没有更新EventValidation隐藏字段导致的问题)。[fixed]\n\t-页面上放置ExtAspNet-Button和ASP.NET-Button,则点击ExtAspNet-Button时激发的是ASP.NET-Button的事件,这个BUG和Extjs2.2.1\u003Cem\u003E中\u003C\u002Fem\u003EExt.Ajax.serializeForm的实现有关。[fixed]\n\t-ExtAspNet内部包含HtmlAgilityPack和Nii.JSON两个开源的第三方类库。[added]\n\t+如果以前你听过不要在ExtAspNet工程\u003Cem\u003E中\u003C\u002Fem\u003E使用ASP.NET标准控件的忠告,那么从v1.3.0版本开始,你可以忘掉这个说法,现在ExtAspNet控件和ASP.NET标准控件和平共处了。[fixed]\n\t\t-如果一个ASP.NET按钮控件要使用ExtAspNet的原生AJAX,只需要设置属性 UseSubmitBehavior=\"false\" 即可。\n\t\t-如果要在一次ExtAspNet的原生AJAX回发时更新ASP.NET控件的值,只需要调用PageManager的公共方法AddAjaxUpdateControl即可(示例:aspnet\u002Faspnet.aspx)。\n\n\n\n+2009-02-27 v1.2 beta9\n\t-网络连接出错时的“Ajax Error”改成更加友好的提示信息“本次连接失败!可能是网络连接出错,请刷新页面重试。”。[fixed]\n\t-自动测试功能会在以后版本\u003Cem\u003E中\u003C\u002Fem\u003E逐步完善。这个版本完成测试框架,采用Extjs\u003Cem\u003E中\u003C\u002Fem\u003EJS函数进行大部分的测试,对于一些难以测试的地方借助jQuery完成。[fixed]\n\t+系统底层代码优化(主要是Javascript的封装和BUG修复)。[fixed]\n\t\t-底层使用Javascript创建一个Window控件的代码由原来的2000字符减少为500个字符。\t\n\t\t-PageContext静态类\u003Cem\u003E中\u003C\u002Fem\u003E的GetPageStateChangedFunction改名为GetConfirmFormModifiedReference,底层代码优化。表示“获取当前页面\u003Cem\u003E中\u003C\u002Fem\u003E表单修改的确认提示框的脚本”。\n\t\t---[updated]删除PageContext\u003Cem\u003E中\u003C\u002Fem\u003E的GetConfirmFormModifiedReference,使用CurrentActiveWindow\u003Cem\u003E中\u003C\u002Fem\u003E的GetConfirmFormModifiedCloseReference\u002FGetConfirmFormModifiedCloseRefreshReference\u002FGetConfirmFormModifiedClosePostBackReference三个方法代替。\n\t\t-不会修改弹出页面的URL(Ext-Window\u003Cem\u003E中\u003C\u002Fem\u003E的IFrame),以前为了实现功能为每个弹出页面添加box_parent_client_id查询字符串\n\t\t-去除PageManager的RegisterPageStateChangedScript属性,现在已经将这个功能实现为静态的JS方法。可以通过PageContext.GetFormModifiedConfirmReference获取此方法的客户端脚本。\n\t\t---注意:以前的项目需要在所有的ASPX页面\u003Cem\u003E中\u003C\u002Fem\u003E查找RegisterPageStateChangedScript属性,并删除,否则会运行错误!\n\t\t-A页面有Ext-Window控件弹出B页面,B页面有Ext-Window控件弹出C页面,B页面的Ext-Window控件设置Target='_parent',则弹出的Ext-Window(C页面)会覆盖整个A页面,这是正确的。\n\t\t---当时如果用户直接访问B页面,就会报JS错误,因为此时找不到B页面的父页面A了。现在的版本修正为如果找不到父页面,则就在当前页面弹出窗口,这样用户直接访问B页面也不会出错了。\n\t\t-Window控件的GetIFramePageStateChangedFunction函数改名为GetConfirmFormModifiedCloseReference,表示“获取先确认IFrame的页面\u003Cem\u003E中\u003C\u002Fem\u003E表单改变,然后关闭弹出窗口的客户端脚本”。\n\t\t---为Window控件增加如下两个方法GetConfirmFormModifiedCloseRefreshReference和GetConfirmFormModifiedClosePostBackReference,表示“先确认表单改变,然后关闭弹出Ext-Window,再然后刷新父页面或回发父页面”。\n\t\t---Window控件的OnClientCloseButtonClick属性如果不设置,则默认采用GetConfirmFormModifiedCloseReference,也即是先判断表单是否更新,然后在关闭窗口。\n\t\t---现在可以很方便的为Window控件的关闭按钮添加关闭后刷新父页面或者关闭后回发父页面的行为。\n\t\t-如果弹出窗口(Window控件)\u003Cem\u003E中\u003C\u002Fem\u003EIFrame的页面不能正常加载(网络暂时出错或页面抛出异常),则此时点击右上角的关闭按钮会报JS错误,因为此时页面尚未加载完毕。\n\t\t---此版本修正了这个BUG,即时页面不能加载完全,也能通过右上角的关闭按钮关闭弹出含IFrame的窗体。\n\t\t-Window控件的IFrameName属性是自动生成的,只读属性。(因为有可能所有的Ext-Window最终都渲染到最外层的页面,为了保证这些IFrame的name不同,IFrameName使用的是GUID,内部处理)。\n\t\t-CurrentActiveWindow改名为ActiveWindow。\n\t\t-[特别注意]GetWriteBackValueReference(string controlClientIds, string value, params string[] values)函数现在的定义是GetWriteBackValueReference(params string[] values)\n\t\t---所有调用GetWriteBackValueReference的地方,需要删除第一个参数(一般是ActiveWindow.GetLoadStateReference())。\n\t\t\n\t\n\n+2009-02-23 v1.2 beta8\n\t-ContentPanel\u003Cem\u003E中\u003C\u002Fem\u003E内容不能自动扩展高度的BUG[feedback:huihuang]。[fixed]\n\t-DropDownList在Ajax回发时不能计算模拟树的\u003Cem\u003E数据\u003C\u002Fem\u003E[feedback:huihuang]。[fixed]\n\t-DropDownList在页面第一次加载时没有不可选择项,则回发时也不会有不可选择项的BUG。[fixed]\n\t-升级底层ExtJS类库为v2.2.1(此版本主要是Chrome的支持和部分内存泄漏问题的修正)。[fixed]\n\t-页面加载过程\u003Cem\u003E中\u003C\u002Fem\u003E的时间信息保存在Javascript变量window.box.timeInfo\u003Cem\u003E中\u003C\u002Fem\u003E。[added]\n\t+增加部分自动测试支持(使用WatiN和NUnit),下个版本将会提供完整的自动测试支持。[fixed]\n\t\n\t\n\n+2008-10-28 v1.2 beta7\n\t-DropDownList没有选\u003Cem\u003E中\u003C\u002Fem\u003E任何一项,回发时报错[feedback:huihuang]。[fixed]\n\t-Window\u003Cem\u003E显示\u003C\u002Fem\u003E位置不对,以及不能拖动的BUG[feedback:huihuang]。[fixed]\n\t+PageContext优化。[fixed]\n\t\t-去除RegisterExclusiveScript静态函数(这是没有原生ajax之前的产物),使用RegisterStartupScript替代。\n\t\t-去除RegisterStartupScript的重载函数,只保留最简单的PageContext.RegisterStartupScript(string script)函数。\n\t\t-Resirect增加重载函数Redirect(string url, string target),其\u003Cem\u003E中\u003C\u002Fem\u003Etarget可能的取值为_self,_parent,_top,分别表示在当前窗口,父窗口,顶级窗口重定向[feedback:jqpeng]。\n\t-Image控件增加ImageWidth\u002FImageHeight\u002FImageCssStyle\u002FImageCssClass\u002FImageAlt属性[feedback:jqpeng]。[fixed]\n\t-发布包\u003Cem\u003E中\u003C\u002Fem\u003E增加一个\u003Cem\u003EWeb\u003C\u002Fem\u003E.config.txt,这是一个空的\u003Cem\u003EWeb\u003C\u002Fem\u003E.config文件,包含BOX基本的配置信息。[fixed]\n\t-ContentPanel的ShowHeader和ShowBorder属性默认也是true(注意更新以前的应用)。[fixed]\n\t-Row和Column布局时,修正IE下设置RowHeight=\"100%\"时\u003Cem\u003E显示\u003C\u002Fem\u003E不正确的BUG。[fixed]\n\t-AccordionLink当鼠标移上和移开时,有背景色的变化效果[feedback:huihuang]。[fixed]\n\t+TabStrip的Tab控件的EnablePostBack属性会在回发时保持(也即是说如果EnablePostBack=true,回发时没改变EnablePostBack的值,则每次切换到此Tab都会回发)。[fixed]\n\t\t-有这样一个效果,如果Tab1默认\u003Cem\u003E显示\u003C\u002Fem\u003E,Tab1的EnablePostBack=true,则页面加载完毕后会回发Tab1一次。\n\t\n\t\n\n+2008-10-20 v1.2 beta6\n\t+使用控件的站点必须建立虚拟目录,否则会报JS错误(即是脚本资源没有加载),却原来是HTTPCompress组件的问题。[fixed]\n\t\t-需要替换新的blowery.\u003Cem\u003EWeb\u003C\u002Fem\u003E.HttpCompress.dll,解决方案见http:\u002F\u002Fpohee.com\u002Fit\u002Fhttp-compression-in-aspnet-20\u002F。\n\t+DropDownList优化。[fixed]\n\t\t-去除EnableFirstItem\u002FFirstItemText\u002FFirstItemValue,这个并不能带来很大的好处,反而容易让开发人员困惑。\n\t\t 现在可以方便的在后台DropDownList1.Items.Insert(0, new ExtAspNet.ListItem(\"全部\", \"-1\"));来达到同样的效果。\n\t\t+如果某项(ListItem)的Value为空字符串,则通过SelectedIndex和SelectedValue不能选\u003Cem\u003E中\u003C\u002Fem\u003E[feedback:jqpeng]。\n\t\t\t-和Asp.net\u003Cem\u003E中\u003C\u002Fem\u003E的保持一致,ListItem的Value值可以为空字符串。 也就是可以这样写DropDownList1.SelectedValue = \"\";\n\t\t-ListItemCollection增加重载函数Add(string text, string value),这样方便后台添加列表项。\n\t-处于布局内的容器控件(Layout!=LayoutType.Container),AutoHeight会自动设置为false(避免开发人员发生此类错误)。[fixed]\n\t-注意,控件的高度指的是整个控件的高度,包含BodyPadding(这和CSS\u003Cem\u003E中\u003C\u002Fem\u003E的height不同,CSS\u003Cem\u003E中\u003C\u002Fem\u003E的height是指内容的高度,除去padding\u002Fborder-width\u002Fmargin)。[fixed]\n\t+为所有控件属性增加在VS\u003Cem\u003E中\u003C\u002Fem\u003E的智能提示。[fixed]\n\t\t-需要将ExtAspNet.XML和ExtAspNet.dll放在一起,这样引用dll时xml会被拷贝到bin目录下,提供VS的智能提示。\n\t+控件的属性如果是枚举类型,如果此属性可以不取值,则默认为None。[fixed]\n\t\t-TriggerIconType.Default -\u003E TriggerIconType.None\n\t\t-SystemIconType.Empty -\u003E SystemIconType.None\n\t\t-RegexPattern.USER_DEFINED -\u003E RegexPattern.None\n\t-表单验证属性名称变化(ValueToCompare-\u003ECompareValue,ControlToCompare-\u003ECompareControl)。[fixed]\n\t+注意:一个属性可以拥有多个值的情况。[fixed]\n\t\t-属性和CSS相关则用空格分隔(比如ColumnWidths,BodyPadding)。\n\t\t-其他的都是逗号分隔(比如ValidateForms,DataKeyNames,DataNavigateUrlFields)。\n\t+AccordionLink实现为控件。[fixed]\n\t\t-可以方便的在子页面(iframe)\u003Cem\u003E中\u003C\u002Fem\u003E通过js切换父页面\u003Cem\u003E中\u003C\u002Fem\u003E选\u003Cem\u003E中\u003C\u002Fem\u003E的菜单项(Accordion-\u003EAccordionLink)(示例在other\u002Faccordion_links_run.aspx,other\u002Faccordion_links_run_iframe_htm)[feedback:jima]。\n\t+确认:可以方便的动态添加控件,并且可以给控件添加服务器端事件(示例在form\u002Fform_dynamic_run.aspx)。[fixed]\n\t\n\t\n\t\n+2008-10-15 v1.2 beta5\n\t-验证表单字段的ValueToCompare属性,为字符串时会出错的BUG。[fixed]\n\t+优化下拉列表。[fixed]\n\t\t-验证下拉列表时,应该取ListItem的Value属性进行验证,而不是Text属性。\n\t\t-DropDownList的Items增加Insert方法(可方便的下拉列表选项添加“全部”)。\n\t\t-DropDownList不支持EmptyText属性。\n\t\t-ListItem启用EnableSelect和SimulateTreeLevel属性,这样就可以直接在前台(ASPX)\u003Cem\u003E中\u003C\u002Fem\u003E设置哪些项不可选择,以及创建模拟下拉树。\n\t\t-DropDownList增加EnableSimulateTree属性(默认为false),如果设置了DataSimulateTreeLevelField,则自动将EnableSimulateTree设置为true。\n\t\n\t\n\n+2008-09-27 v1.2 beta4\n\t+EnableLargeHeader属性对所有容器的效果一样,Accordion的属性EnableLargeHeader只会改变Accordion的标题大小,而不会对AccordionPanel起作用(示例见other\u002Faccordion_run.aspx)。[fixed]\n\t\t-Accordion去除EnableHightlight属性,AccordionPanel增加EnableHightlight属性。\n\t\t-影响以前使用Box的应用,需要将Accordion的属性去掉,然后为每个AccordionPanel增加EnableLargeHeader和EnableHightlight属性。\n\t-AccordionPanel鼠标移上去的样式调整(现在没有下面的一条白线了)。[fixed]\n\t+AccordionPanel增加Links属性,可以绑定列表\u003Cem\u003E数据\u003C\u002Fem\u003E到AccordionPanel,呈现的是链接的列表(示例在other\u002Faccordion_links_run.aspx)。[fixed]\n\t\t-原来放置在AccordionPanel\u003Cem\u003E中\u003C\u002Fem\u003E的容器,比如ContentPanel需要在外层加上\u003CItems\u003E标签。\n\t\t-适当增大AccordionPanel\u003Cem\u003E中\u003C\u002Fem\u003E链接的高度20px-\u003E22px,同时对链接的样式也做了微调。\n\t\t-通过BodyPadding控制链接列表的边距。\n\t\t-这样能大大减少ASPX\u003Cem\u003E中\u003C\u002Fem\u003EHTML代码和Javascript代码的书写,可以在后台动态添加链接,效果很赞,此需求由马季提出。\n\t\n\t\n\t\n+2008-09-25 v1.2 beta3\n\t+代码优化与设计时支持(尚需要不断完善,目前可以在ASPX页切换到“设计时”,方便属性的更改和事件处理函数的添加)。[fixed]\n\t\t-Panel\u002FGroupPanel\u002FContentPanel\u002FTree\u002FHiddenField\u002FPageLoading\n\t\t-TabStrip\u002FToolbar\n\t-TabStrip去除Plain属性,增加EnableTitleBackgroundColor(默认为true)。[fixed]\n\t-向Form\u003Cem\u003E中\u003C\u002Fem\u003E动态添加控件的BUG,现在form\u002Fform_dynamic_run.aspx示例已经能正确运行。[fixed]\n\t+大部分容器的子控件集合更正为Items(以前有些是Rows)。[fixed]\n\t\t-影响的控件包括Toolbar\u002FAccordion\u002FAccordionPanel\u002FGroupPanel\u002FPanel\u002FSimpleForm\u002FWindow等。\n\t\t-保留Form的Rows(FormRowCollection)属性和Grid的Rows属性(GridRowCollection)。\n\t\t-保留TabStrip的Tabs(TabCollection)属性。\n\t\t-保留PageLayout\u002FBorderLayout的Regions(RegionCollection)属性。\n\t-预祝今晚神七发射成功。\n\t\n\t\n\t\n+2008-09-22 v1.2 beta2\n\t+Grid选\u003Cem\u003E中\u003C\u002Fem\u003E项(SelectedRowIndexArray)在ajax回发过程\u003Cem\u003E中\u003C\u002Fem\u003E存在BUG [feedback:xmzhu]。[fixed]\n\t\t-表现为对Grid进行多次删除添加操作后,SelectedRowIndexArray选\u003Cem\u003E中\u003C\u002Fem\u003E项\u003Cem\u003E中\u003C\u002Fem\u003E会存在当前不存在的行序号,导致服务器端遍历选\u003Cem\u003E中\u003C\u002Fem\u003E项时数组越界。所有使用box控件的应用程序都受到此BUG的影响,需尽快更新到新版本。\n\t+代码优化与设计时支持(示例\u003Cem\u003E中\u003C\u002Fem\u003E表单控件都已支持设计)。[fixed]\n\t\t-PageManager\u002FSimpleForm\u002FButton\u002FHyperLink\u002FLabel\u002FImage\u002FLinkButton\u002FTextBox\n\t\t-TriggerBox\u002FTwinTriggerBox\u002FWindow\u002FTextArea\u002FHtmlEditor\u002FDatePicker\u002FNumberBox\n\t\t-CheckBox\u002FRadioButton\u002FRadioButtonList\u002FDropDownList\n\t\t-Grid\n\n\n\n+2008-09-19 v1.2 beta1\n\t-Image\u002FLinkButton\u002FHyperLink增加一些Ajax可更新属性。[fixed]\n\t+隐藏的方式由HideMode属性控制Visibility\u002FOffsets\u002FDisplay。[fixed]\n\t\t-修正Form\u002FSimpleForm\u003Cem\u003E中\u003C\u002Fem\u003E隐藏一个表单字段(Hidden=false)会占据页面空间的BUG。\n\t-ToolbarText\u002FToolbarFill\u002FToolbarSeparator在ASPX\u003Cem\u003E中\u003C\u002Fem\u003E设置Hidden=true不起作用的BUG [feedback:jbzhang]。[fixed]\n\t-Button去除MarginRight属性(可以通过CssStyle=\"margin-right:5px;\"达到相同的效果)[fixed]\n\t\n\t\n\t\n+2008-09-09 v1.1\n\t+Toolbar去除IsPageMenu属性,在网报\u003Cem\u003E中\u003C\u002Fem\u003E可以用自定义样式实现,而不应该写在控件\u003Cem\u003E中\u003C\u002Fem\u003E。[fixed]\n\t\t-网报:CssClass=\"toolbar-pagemenu\" CssStyle=\"border:0px;\",同时定义样式:.toolbar-pagemenu{ background: rgb(208, 222, 240) url(..\u002Fimages\u002Fpagemenu_toolbar_background.gif) repeat-x left top;}。\n\t-Region去除默认的Layout=Fit,如果希望Region使用Fit\u002FAnchor\u002FColumn\u002FRow等布局的话,需要手工指定。[fixed]\n\t-ToolbarSeparator\u002FToolbarFill在Ajax更新Hidden属性的BUG。[fixed]\n\t+布局整理。[fixed]\n\t\t-新增Column\u002FAbsolute\u002FRow三种布局,加上以前的Container\u002FFit\u002FAnchor\u002FAccordion\u002FBorder\u002FForm六种布局,总共有9\u003Cem\u003E中\u003C\u002Fem\u003E布局可供使用。\n\t\t-其\u003Cem\u003E中\u003C\u002Fem\u003E一些控件默认使用一种布局:SimpleForm(Form)\u002FForm(Form)\u002FPanel-GroupPanel(Container)\u002FAccordion(Accordion)\u002FPageLayout(Border)\u002FBorderLayout(Border)\u002FTabStrip(Card),所有布局控件默认的布局是Container。\n\t\t-经常用到的布局控件:SimpleForm\u002FForm\u002FAccordion\u002FTabStrip\u002FBorderLayout,经常用到的布局:Fit\u002FRow\u002FAnchor\n\t\n\t\n\t\n+2008-09-08 v1.1 beta7\n\t-MenuButton\u002FMenuHyperLink增加HideOnClick属性,如果一个菜单项的作用仅仅为了弹出下级菜单,点击没反应,则可以这样设置HideOnClick=\"false\" CssStyle=\"cursor:default;\" [feedback:huayu]。[fixed]\n\t-MenuButton\u002FMenuHyperLink\u002FMenuSeparator\u002FMenuText增加Hidden属性(此属性是Ajax可更新属性,如果需要在Ajax时\u003Cem\u003E显示\u003C\u002Fem\u003E隐藏菜单,请使用此属性而不是Visible属性)。[fixed]\n\t+大部分的ExtAspNet控件增加Hidden属性(少数几个控件没有此属性:Menu),这样在Ajax时可以\u003Cem\u003E显示\u003C\u002Fem\u003E隐藏控件。[fixed]\n\t\t-注意Visible和Hidden的区别:Visible=false的属性不会渲染到客户端,Hidden=true的控件渲染到客户端但是隐藏。\n\t\t-US的ExtAspNet改造强烈依赖于此属性,这个版本发布后可以继续。\n\t\t-网报\u003Cem\u003E中\u003C\u002Fem\u003E唯一没有用到ExtAspNetAjax的地方就是\u003Cem\u003E显示\u003C\u002Fem\u003E隐藏表单字段,现在也可以使用Ajax了。\n\n\n\n+2008-09-04 v1.1 beta6\n\t-PageContext.Redirect支持普通页面转向和ExtAspNetAjax下页面转向。[fixed]\n\t+模拟树的下拉列表的BUG(会使一些可选项变成不可选项)[feedback:xmzhu]。[fixed]\n\t\t-因为if(\"0,2,9,11,\".indexOf('1,')\u003E=0){ok},这显然是不对的,此BUG涉及很多控件(Grid,DropDownList,TabStrip)。\n\t\t-解决方法:testValue += '';if(domValue.split(',').indexOf(testValue) \u003E= 0){ok}。\n\t-DropDownList在Ajax时应该先更新\u003Cem\u003E数据\u003C\u002Fem\u003E再设置选定项 [feedback:xmzhu]。[fixed]\n\t-Button\u002FMenuButton增加Ajax可更新属性OnClientClick [feedback:xmzhu]。[fixed]\n\t-Tree的Ajax支持(尚需优化)。[fixed]\n\t\n\t\n\n+2008-09-02 v1.1 beta5\n\t-DropDownList如果第一次没有绑定值,应该绑定到[[]](二维数组),而不是[](一维数组)。[fixed]\n\t-模拟树的DropDownList,在Ajax重新绑定DataSource后,保持项是否可选状态是最新的(页面第一次加载时,即使没有\u003Cem\u003E数据\u003C\u002Fem\u003E也需要设置DataTextField\u002FDataValueField\u002FDataSimulateTreeLevelField\u002FDataEnableSelectField等属性的值,否则Ajax回发时会出错)。[fixed]\n\t-UserControlConnector导致的Ajax错误,去除UpdatePanelConnector控件(以后不会用AspnetAjax,这个控件已经完成使命)。[fixed]\n\t-不要使用Asp.net的控件HiddenField,而是使用ExtAspNet的HiddenField,因为Asp.net的控件在Ajax不会被更新,所以会导致视图状态不一致的错误。[fixed]\n\t-网报Ajax整合基本完成(除了待审批-\u003E下一步[审核\u002F归档\u002F出纳]操作,由于需要\u003Cem\u003E显示\u003C\u002Fem\u003E隐藏表单字段,目前Ajax不支持,使用的还是普通的PostBack)。[fixed]\n\t-IE下,RadioButtonList\u003Cem\u003E中\u003C\u002Fem\u003E项如果存在汉字,则会换行的BUG。[fixed]\n\t-增加两个Theme[Slate\u002FBlack](样式尚需完善)。[fixed]\n\t\n\t\n\t\n+2008-09-01 v1.1 beta4\n\t-非当前Tab\u003Cem\u003E中\u003C\u002Fem\u003E如果有ContentPanel,则在页面上方会有空白(可以通过设置EnableDeferredRender=false解决,但会减慢页面的加载速度),现在已经解决这个问题。[fixed]\n\t-RadioButtonList去除EnableBackgroundColor\u002FEnableLightBackgroundColor属性,背景色是透明的,也就是和父控件(SimpleForm\u002FForm)的背景色一致。[fixed]\n\t-TwinTriggerBox的第一个Trigger图标不会先\u003Cem\u003E显示\u003C\u002Fem\u003E再隐藏,而是直接隐藏掉(如果用户设置ShowTrigger1=false)。[fixed]\n\t-\u003Cem\u003EWeb\u003C\u002Fem\u003E.config\u003Cem\u003E中\u003C\u002Fem\u003E增加配置项FormLabelWidth=\"80\"(默认为80),同时PageManager增加FormLabelWidth属性用来控制页面上所有SimpleForm\u002FForm的表单字段标题的宽度。[fixed]\n\t+完善Ajax。[fixed]\n\t\t-RadioButtonList增加Ajax可更新属性SelectedIndex(SelectedValue\u002FSelectedItem)。\n\t\t-DropDownList增加Ajax可更新属性Enable\u002FSelectedIndex(SelectedValue\u002FSelectedItem)\u002FDataSource。\n\t\t-Grid增加Ajax可更新属性Columns(也就是说Grid列在回发时隐藏\u003Cem\u003E显示\u003C\u002Fem\u003E了一些,也能正确的Ajax)。\n\t\t-ToolbarText增加Ajax可更新属性Text。\n\t\t\n\t\t\n\t\t\n+2008-08-31 v1.1 beta3\n\t-TabStrip增加EnableDeferredRender属性(是否启用延迟加载Tab,默认启用)。[fixed]\n\t-重定向页面,使用系统的方法 PageContext.Redirect(string url),使用Response.Redirect方法会出错。[fixed]\n\t+安全的Ajax设计。[fixed]\n\t\t-这个版本Ajax和上个版本(v1.1beta1)在设计思路上有很大区别,同时在速度上会有进一步的提升。\n\t\t-基本思想:安全的Ajax交互,明确Ajax回发时支持控件哪些属性的改变,这将适合90%的应用场景(并且具有极快的反应速度),对于需要UI大改动的可采用常规回发,系统提供控件级别的EnableAjax属性。\n\t\t-整理支持Ajax的控件属性改变列表(所有被支持的属性改变都是安全的、快速的,所有不被支持的属性改变不会对UI起作用,同时是安全的,不会有js错误)。\n\t-网报Ajax整合(目前只支持所有的列表页面)(v0.8.1)。[fixed]\n\t\n\t\n\t\n+2008-08-29 v1.1 beta1\n\t+Window控件是否弹出的状态在回发时维持。[fixed]\n\t\t-控件设计的一个原则,凡是可以在客户端改变的属性都应该在回发时保持属性的状态。\n\t+完全抛弃Asp.NetAjax,ExtAspNet控件内置Ajax支持。[fixed]\n\t\t-这是一个值得骄傲的设计,可以明显提高页面回发的速度(相比普通的回发和Asp.netAjax的回发),对于IFrame框架的交互也起到很好的加速效果。\n\t\t-不需要做任何配置,所有的回发都是Ajax(在\u003Cem\u003EWeb\u003C\u002Fem\u003E.config和PageManager\u003Cem\u003E中\u003C\u002Fem\u003E有设置启用Ajax回发的属性-EnableAjax-默认为true)。\n\t\t+在这种设计下,其实可以完全抛弃Javascript。\n\t\t\t-比如简单的点击一个按钮弹出窗口,可以在Button的OnClick事件\u003Cem\u003E中\u003C\u002Fem\u003E设置Window1.Popup=true,也可以注册Button的OnClientClick=Window1.GetShowReference()。\n\t\t\t-第一种方法需要回发,但是我们内置的Ajax支持能很快的返回需要的结果并解析,在网络速度很快的情况下和第二种方法差别不是很大。\n\t\t\t-推荐的做法是尽量用客户端实现,客户端实现复杂的直接用服务器端实现。\n\t\t+目前ExtAspNetAjax的限制。\n\t\t\t-只对ExtAspNet控件起作用,对Asp.net控件不起作用。\n\t\t\t-对容器控件(有子控件的控件)不起作用,只对最底层的控件起作用。\n\t\t\t-对改变控件的Visible属性会有错误。\n\t\t\t-Window控件的属性改变只有少数几个起作用(Popup,IFrameUrl)。\n\t-PageManager增加属性EnablePageLoading和EnableAjaxLoading(启用页面第一次加载标示和Ajax加载标示,默认都为true),所以如果使用系统默认的加载标示就不必每个页面都添加PageLoading控件。[fixed]\n\t-Grid\u003Cem\u003E中\u003C\u002Fem\u003E的回发事件(主要是LinkButtonField和CheckBoxField(RenderAsStaticField=false))要延迟0ms执行,这样当前行被选\u003Cem\u003E中\u003C\u002Fem\u003E的状态在回发后会得到保持。[fixed]\n\t-Grid选\u003Cem\u003E中\u003C\u002Fem\u003E行的状态在第一次回发时不能保持的BUG。[fixed]\n\t\n\t\n\t\n+2008-08-26 v1.0\n\t+已知问题:IE的ActiveX插件IE Developer Toolbar会对IFrame的加载造成0.5m左右的延迟。\n\t\t-主要是父页面加载一个比较大的css文件(~100k),则每次打开iframe页面,onload事件的调用都会有500ms左右的延迟,在测试IE性能时要禁用此插件。\n\t+优化弹出窗口\u003Cem\u003E中\u003C\u002Fem\u003EIFrame的\u003Cem\u003E显示\u003C\u002Fem\u003E速度。[fixed]\n\t\t-在当前页面弹出窗口需要~20ms,在父页面弹出窗口需要100~300ms。通过缓存弹出的窗口实例,从而第二次弹出窗口不再需要创建时间。\n\t-PageLayout的Region增加SplitColor属性,默认的背景色是透明的。(在网报\u003Cem\u003E中\u003C\u002Fem\u003E需要设置SplitColor=\"#CADDF7\",以便分隔符的颜色和Toolbar的颜色一致)[fixed]\n\t+PageManager增加属性Theme、Language、FormMessageTarget、FormOffsetRight等属性,这些属性可以在\u003Cem\u003EWeb\u003C\u002Fem\u003E.config\u003Cem\u003E中\u003C\u002Fem\u003E设置(推荐方法),也可以为每个页面设置。[fixed]\n\t\t-一个典型的应用是为每个用户设置不同的皮肤(根据用户浏览器\u003Cem\u003E中\u003C\u002Fem\u003ECookie设置的值)(示例在default.aspx)。\n\t-TreeNode增加属性SingleClickExpand,表示点击可切换节点的折叠展开状态。[fixed]\n\t+TabStrip\u003Cem\u003E中\u003C\u002Fem\u003E非当前Tab会延迟渲染。[fixed]\n\t\t-这会明显加快页面的渲染速度,网报\u003Cem\u003E中\u003C\u002Fem\u003E一个典型的费用审批页面可以减少200ms的渲染时间。\n\t\t-由于非当前Tab不会在页面加载时渲染,所以那些Tab\u003Cem\u003E中\u003C\u002Fem\u003E的节点在页面加载后也是不可见的,需要将相关的脚本移动到控件的render事件\u003Cem\u003E中\u003C\u002Fem\u003E。\n\t-不能比较两个DataPicker大小的BUG。[fixed]\n\t-TabStrip延迟加载引起的BUG(非当前Tab\u003Cem\u003E中\u003C\u002Fem\u003E的ContentPanel会占据页面空间,已修正)。[fixed]\n\t-全新的ExtAspNet.Examples(基础知识\u002F表单控件\u002F\u003Cem\u003E数据\u003C\u002Fem\u003E绑定\u002F容器布局\u002FIFrame框架)。[fixed]\n\t\n\t\n\t\n+2008-08-19 v0.4 beta6\n\t+PageManager增加两个属性(EnableInlineStyleJavascript\u002FApplyParentStyleJavascript),可以在IFrame页面\u003Cem\u003E中\u003C\u002Fem\u003E使用父页面的脚本和样式(示例在iframe\u002Fdefault.aspx和iframe\u002Fpage3.aspx)。[fixed]\n\t\t-测试发现,IFrame页面的加载速度并没有明显加快,可以先不使用此属性。\n\t-RadioButtonList放在在BorderLayout\u003Cem\u003E中\u003C\u002Fem\u003E\u003Cem\u003E显示\u003C\u002Fem\u003E不了的BUG [feedback:zgjiang2]。[fixed]\n\t+extjs的BUG,当页面\u003Cem\u003E中\u003C\u002Fem\u003E含有iframe时,Ext.onReady会被调用两次(IE6\u002FIE7)(http:\u002F\u002Fwww.extjs.net\u002Fforum\u002Fshowthread.php?t=43246)(示例在test.aspx)[fixed]\n\t\t-现在的解决方法是在初始化时:if(this.initialized){return;}this.initialized=true;\n\t+需要先回发页面再弹出IFrame窗口。[fixed]\n\t\t-在回发时设置窗口的Popup和IFrameUrl属性,因为这些属性是可以保持状态的,所以在关闭窗口时要注意设置Popup=false。\n\t\t-另一种做法(推荐):PageContext.RegisterStartupScript(Window99.GetShowReference(\".\u002Fsimpleform.aspx\"));。\n\t\n\t\t\n\t\n+2008-08-15 v0.4 beta5\n\t-点击关闭窗口的按钮,在IE6下会有JS错误。[fixed]\n\t-增加BorderLayout控件,示例在iframe\u002Fborderlayout.aspx。[fixed]\n\t+Radiobuttonlist\u003Cem\u003E显示\u003C\u002Fem\u003E有重影(示例在radio.aspx)。[fixed]\n\t\t-全新的样式。\n\t\t-去除Horizontal属性,增加ColumnNumber(可以设置渲染成几列)。\n\t\t-GetValueReference取得的值不正确的BUG。\n\t-动态向Form\u003Cem\u003E中\u003C\u002Fem\u003E添加FormRow,并动态的向FormRow\u003Cem\u003E中\u003C\u002Fem\u003E添加表单字段,以及如何取得表单字段的值。(示例在form_dynamic.aspx)[fixed]\n\t+IFrame弹出窗口关闭后回发父页面,则会多加载IFrame一次,再次打开窗口会重复加载IFrame2-3次[feedback:xmzhu]。[fixed]\n\t\t-这是一个重要的BUG,会严重影响页面的加载速度。原因是通过脚本改变的IFrameUrl会在回发时保持状态,从而回发父页面后Window\u003Cem\u003E中\u003C\u002Fem\u003E的IFrame被添加到页面,而这是不需要的。\n\t\t-现在\"是否弹出窗口、窗口标题、IFrameUrl\"在客户端的改变,不会影响服务器端的属性,也即是不保持状态。此问题解决。(示例在button_iframe.aspx)\n\t\n\t\n\t\n+2008-08-13 v0.4 beta4\n\t-点击关闭窗口的按钮,在IE下会有JS错误。[fixed]\n\t-Window的右上角关闭图标增加提示,优化事件响应。[fixed]\t\n\t-Window的代码重构。[fixed]\t\n\t+修正一个的内存泄漏。[fixed]\n\t\t-IE7下测试,打开iframe\u002Fdefault.aspx页面,iexplorer占内存68.368M。\n\t\t-内存存在泄漏时,点击iframe\u002Fpage3.aspx页面8次后iexplorer占118.792M内存。\n\t\t-修正后,点击iframe\u002Fpage3.aspx页面8次后iexplorer占76.492M内存。\n\t\t-IE窗口最小化时,IE会自动进行垃圾回收。\n\t\n\t\n\t\n+2008-08-12 v0.4 beta3\n\t-底层的javascript框架Extjs升级为v2.2,Grid的渲染速度有很大提升。[fixed]\n\t-Grid的EnableDelayRender默认为true(如果没有设置Grid的高度或通过布局间接设置高度,则行不可见,可以通过AutoHeight=\"true\"解决)。[fixed]\n\t+页面正在加载的提示尽早的\u003Cem\u003E显示\u003C\u002Fem\u003E出来。[fixed]\n\t\t-首先在执行js来完成页面渲染之前延迟5ms,以便浏览器把当前页面内容\u003Cem\u003E显示\u003C\u002Fem\u003E出来。\n\t\t-加载js脚本的script标签放置在页面的最后,放置加载js而阻塞PageLoading的\u003Cem\u003E显示\u003C\u002Fem\u003E。\n\t\n\t\n\t\n+2008-08-08 v0.4 beta2\n\t-TabStrip延时加载出错。[fixed]\n\t-Window的IFrameUrl处理的BUG,比如Pages_ExtAspNet目录下的页面应该为.\u002FFE_ApplyEditor.aspx或~\u002FPages_ExtAspNet\u002FFE_ApplyEditor.aspx。[fixed]\n\t-Window的WindowPosition=\"Center\"并且Target=\"_parent\",则会JS错误。[fixed]\n\t-实现网报首页下拉菜单和左侧菜单的导航功能。[fixed]\n\t-Window的创建在页面\u003Cem\u003E显示\u003C\u002Fem\u003E后进行,不计算在js渲染时间内。[fixed]\n\t-优化费用申请页面(尽量减少不必要的层次嵌套)。[fixed]\n\t-button_iframe.aspx默认会加载form.aspx页面(Window控件的BUG)。[fixed]\n\t-Window\u003Cem\u003E中\u003C\u002Fem\u003E的保存并关闭按钮和Asp.netAjax冲突。[fixed]\n\t-优化关闭Window的js脚本,减少写到页面的js大小。[fixed]\n\t-加快“保存并关闭”按钮关闭窗口的速度,使用PageContext.RegisterExclusiveScript(CurrentActiveWindow.GetClosePostBackReference());,示例在(simpleform.aspx)。[fixed]\n\t\n\t\n\t\n+2008-08-05 v0.4 beta1\n\t-DropDownList去除Traditional属性,和传统的Asp.net控件一样不可编辑。[fixed]\n\t-DropDownList增加SelectedText属性(去除了模拟树时通过SelectedItem.Text的多余html字符)。[fixed]\n\t-为了加快渲染速度,去掉一些特效(比如Panel的折叠效果,Grid的拖动列效果等)[feedback:dcding]。[fixed]\n\t-将生成的js对象的名称简单化,这样可以减少生成的js内容,加快页面加载速度(一个典型页面的js由原来的33.0k降低为21.4k)。[fixed]\n\t+弹出窗口\u003Cem\u003E中\u003C\u002Fem\u003E,点击按钮回发然后点击关闭按钮,出现js错误 [feedback:xmzhu]。[fixed]\n\t\t-因为在页面的Page_Load\u003Cem\u003E中\u003C\u002Fem\u003E,if (!IsPostBack){PageContext.RegisterPageStateChangedStartupScript();}通过这样方法向页面注册了一段脚本,但是这段脚本在回发时没有注册到页面,因为js调用此脚本时报错。\n\t\t-一种解决方法是将向页面注册脚本的函数移动到if语句的外面,即每次都向页面注册此脚本。\n\t\t-另一种办法就是在PageManager控件\u003Cem\u003E中\u003C\u002Fem\u003E增加RegisterPageStateChangedScript(向页面注册监视页面\u003Cem\u003E中\u003C\u002Fem\u003E表单内容改变的脚本)的属性(会在每次页面回发(包含ajax回发)时注册脚本)(示例在button_iframe.aspx\u002Fsimpleform.aspx)。\n\t+PageManager控件增加ExecuteOnReadyWhenPostBack属性(示例在onreadyscript.aspx)。[fixed]\n\t\t-这个手工添加onReady函数能够在每次页面回发时都注册脚本(包括Ajax局部回发),这就避免了手工去做的麻烦(已经在网报\u003Cem\u003E中\u003C\u002Fem\u003E遇到这种情况)。\n\t-每个页面必须添加一个PageManager控件,否则会出错,同时去除DesignTimeStyle控件(作为PageManager的属性出现)。[fixed]\n\t-TextField等表单字段增加Readonly属性。[fixed]\n\t+全新设计的IFrame的架构(尽可能和基于MasterPage的架构保持兼容,和Asp.net Ajax保持兼容)。[fixed]\n\t\t-最大的好处是可以减少页面下载完毕后Javascript渲染时间(可以节约一般的渲染时间)。(所有示例在iframe文件夹下)\n\t\t+示例1,通过点击按钮弹出IFrame窗口,可直接关闭父页面,也可在关闭后刷新或回发父页面。(default.aspx\u002Fpage2.aspx\u002Fsimpleform.aspx)\n\t\t\t-虽然IFrame和Master两种架构差异迥然,或许你以为需要修改一堆代码来完成这种转换,起初我也是这么认为的,但是现在你所要做的仅仅是为Window控件增加一个属性(Target=\"_parent\"),就完成了两种框架的转换,是不是很酷。\n\t\t\t-显然,控件本身封装了大量的代码,简单来看现在有三个页面(default.aspx(A)\u002Fpage2.aspx(B)\u002Fsimpleform.aspx(C)),其\u003Cem\u003E中\u003C\u002Fem\u003EA包含B页面,当你在B\u003Cem\u003E中\u003C\u002Fem\u003E打开包含有页面C的窗口时,窗口不是在B\u003Cem\u003E中\u003C\u002Fem\u003E打开,而是在A\u003Cem\u003E中\u003C\u002Fem\u003E打开,这样才能保证窗口覆盖整个页面,当你从C\u003Cem\u003E中\u003C\u002Fem\u003E返回需要回发页面B时,却发现取得的是A页面,因为我们窗口是在A页面\u003Cem\u003E中\u003C\u002Fem\u003E创建的。我会通过一篇文章来揭示这一过程,敬请期待。\n\t\t-示例2,Grid\u003Cem\u003E中\u003C\u002Fem\u003E弹出窗口。(default.aspx\u002Fpage3.aspx\u002Fsimpleform.aspx)\t\n\t\t+示例3,TriggerBox弹出窗口。(default.aspx\u002Ftriggerbox.aspx\u002Fsimpleform.aspx)\t\n\t\t\t-在整个页面弹出窗口或者在当前页面弹出窗口,仅仅设置Window的Target属性即可。\n\t\t-示例4,弹出窗口\u003Cem\u003E中\u003C\u002Fem\u003E的弹出窗口。\n\t-对整个Examples更新测试。[fixed]\n\t\n\t\n\t\n+2008-07-31 v0.3 beta12\n\t-IE下TabStrip在Ajax回发后不会去掉x-hide-display样式,导致Tab\u003Cem\u003E显示\u003C\u002Fem\u003E为空的BUG。[fixed]\n\t-对TabStrip\u002FPanel\u002FWindow\u003Cem\u003E中\u003C\u002Fem\u003E的IFrame重新设计,如果设置IFrameUrl=\"#\"或者\"about:blank\",则不渲染iframe到页面节点,同时第二次打开Window\u003Cem\u003E中\u003C\u002Fem\u003E的IFrame不会有残影出现。[fixed]\n\t-如果TabStrip的Tab不是激活Tab并且设置了IFrameUrl,则会延迟加载(示例在tabstrip_iframe.aspx)。[fixed]\n\t-Tree控件,点击一个节点自动回发,则当前点击的那个节点的选\u003Cem\u003E中\u003C\u002Fem\u003E状态不会保持的BUG [feedback:zgjiang2]。[fixed]\n\t+规范关闭窗口时提示用户保存已经修改的内容提示的调用方式(包含iframe\u003Cem\u003E中\u003C\u002Fem\u003E关闭按钮和window右上角关闭图标的调用方式)(示例在grid_iframe.aspx\u002Fsimpleform.aspx)。[fixed]\n\t\t-内部实现上,点击“保存并关闭按钮”,可以将关闭窗口的脚本更早的执行(在simpleform.aspx,PageContext.RegisterStartupScript增加重载函数),而不是原来的先创建整个页面UI,再关闭窗口。\n\t-参照Yslow的评分规则,将JS文件引用由head移动到body\u003Cem\u003E中\u003C\u002Fem\u003E。[fixed]\n\t-Firefox下,如果页面太长会出滚动条,原来在ViewPort样式\u003Cem\u003E中\u003C\u002Fem\u003E有body{overflow:hidden;}。[fixed]\n\t+IFrame内的页面宽度和高度会自动设置(是不是还在为1px\u002F2px的白边而烦恼,现在不用了:-)(示例在iframe_autosize.aspx\u002Fsimpleform.aspx\u002Fsimpleform2.aspx)[fixed]\n\t\t-增加PageManager控件(需要指定AutoSizePanelID,即需要设置宽度和高度为整个页面的宽度和高度的Panel),HideScrollbar属性用于隐藏滚动条(IE\u002FFirefox)。\n\t\n\t\n\t\n+2008-07-24 v0.3 beta11\n\t-\u003Cem\u003Eweb\u003C\u002Fem\u003E.config配置信息\u003Cem\u003E中\u003C\u002Fem\u003EMessageTarget改名为FormMessageTarget,增加FormOffsetRight配置项,用来定义全局表单字段距离右边界的宽度,同时每个表单字段都增加OffsetRight属性 [feedback:jima]。[fixed]\n\t-Window在回发时设置的Title不起作用的BUG。[fixed]\n\t-增加Image控件 [feedback:jima]。[fixed]\n\t-Tree控件,如果一个节点不是叶子节点并且没有子节点,则应把它的Expanded设置为false,否则会引起页面死循环回发 [feedback:zgjiang2]。[fixed]\n\t-Image增加ToolTipTitle\u002FToolTipAutoHide两个属性,当提示信息特别长时,可以让用户阅读完毕之后手工关闭提示信息(示例在hyperlink.aspx)。[fixed]\n\t-去掉DropDownList控件的Text属性(强制性),可以通过设置SelectedValue来设置选\u003Cem\u003E中\u003C\u002Fem\u003E哪一项 [feedback:xmzhu]。[fixed]\n\t-过滤提示消息\u003Cem\u003E中\u003C\u002Fem\u003E的换行符(转换为\u003Cbr\u002F\u003E),否则提示信息可能导致页面渲染错误 [feedback:dcding]。[fixed]\n\t\n\t\n\t\n+2008-07-23 v0.3 beta10\n\t+完善Tree控件。[fixed]\n\t\t-如何将\u003Cem\u003E数据\u003C\u002Fem\u003E库\u003Cem\u003E中\u003C\u002Fem\u003E的\u003Cem\u003E数据\u003C\u002Fem\u003E绑定到Tree(示例在tree2_bind_database.aspx)。\n\t\t-ajax加载树节点,放在UpdatePanel\u003Cem\u003E中\u003C\u002Fem\u003E才有ajax的效果(示例在tree2_ajax.aspx)。\n\t\t-更改TreeNode的ID为NodeId,否则两个树\u003Cem\u003E中\u003C\u002Fem\u003E不能有相同ID的TreeNode,这是不合理的。\n\t-Grid的GridColumn的ID改名成ColumnId,否则同一个页面放置两个Grid,它们的GridColumn的ID不能同名,这是不合理的。注意需要更新以前的代码![fixed]\n\t-Grid所有类型的列增加DataTooltipField\u002FDataTooltipFormatString两个字段,以\u003Cem\u003E显示\u003C\u002Fem\u003EToolTip(示例在grid.aspx)。[fixed]\n\t\n\t\n\t\n+2008-07-22 v0.3 beta9\n\t+IE6下,左侧导航链接的选\u003Cem\u003E中\u003C\u002Fem\u003E样式,以及鼠标移上去和移开的样式不对。[fixed]\n\t\t-发现原来ie6不能正确解析li的高度,必须手工设置才行(style=\"height:20px;\")。\n\t+IE6\u002FIE7下,模拟树的下拉列表如果文字长度太长,则\u003Cem\u003E显示\u003C\u002Fem\u003E的文字会换行,导致错位。[fixed]\n\t\t-虽然最后未能解决\u003Cdiv style=\"width: 60px; white-space: nowrap; overflow: hidden; border: solid 1px red;\"\u003E\u003Cdiv style=\"width: 16px; height: 18px; float: left;\"\u003E##\u003C\u002Fdiv\u003E差旅交通费\u003C\u002Fdiv\u003E在IE和Firefox下\u003Cem\u003E显示\u003C\u002Fem\u003E的不同效果。\n\t\t-但是通过用\u003Cimg src=\"##\" \u002F\u003E来代替\u003Cdiv style=\"background:url(##)\" \u002F\u003E,从而实现FF和IE下样式的统一。\n\t\t-刚看到old9的解决方案:把“差旅交通费”改成“\u003Cspan style=\"margin-right: -1000px;\"\u003E差旅交通费\u003C\u002Fspan\u003E”,在IE下和FF下的都不换行,:-)\n\t-LinkButton增加OnClick事件 [feedback:huihuang]。[fixed]\n\t-Window通过设置IFrameUrl和Popup不起作用的BUG。[feedback:xmzhu]。[fixed]\n\t+增加树控件(Tree)(示例在tree2.aspx)。[fixed]\n\t\t-可以在回发时维持树的状态(选\u003Cem\u003E中\u003C\u002Fem\u003E行,折叠\u002F展开,CheckBox)。\n\t\t-可以通过Inline的方式添加树节点,也可以绑定到XmlDocument\u002FXmlDataSource\u002FSiteMap。\n\t\t-点击树节点可以链接到页面,也可以引发PostBack事件,可以添加自定义脚本。\n\t\n\t\n\t\n+2008-07-16 v0.3 beta8\n\t+ContentPanel\u003Cem\u003E中\u003C\u002Fem\u003E放置ExtAspNet控件,则渲染时会出现各种问题,比如下拉列表\u003Cem\u003E显示\u003C\u002Fem\u003E样式出错,Grid没了滚动条等等。[fixed]\n\t\t-隐蔽性非常强,原来在ContentPanel\u003Cem\u003E中\u003C\u002Fem\u003E渲染ExtAspNet控件,如果容器的display='none',则会出现各种问题(主要是大小不对)。\n\t\t 必须设置容器为visibility='hidden',然后在渲染完成后\u003Cem\u003E显示\u003C\u002Fem\u003E容器。\n\t\t-现在Grid只要\u003Cem\u003E显示\u003C\u002Fem\u003E的设置高度和宽度,或者隐式的设定宽度高度(通过Anchor或Fit布局实现),只要超过Grid容器就会\u003Cem\u003E显示\u003C\u002Fem\u003E滚动条。\n\t+IE6下,在应用Asp.NetAjax后,Form\u003Cem\u003E中\u003C\u002Fem\u003E字段的宽度渲染不正确。[fixed]\n\t\t-调试相当困难,如果你有过在IE下通过alert发现问题的经历,你就能明白。\n\t\t-最后发现IE6下应用Asp.NetAjax后不仅Form\u003Cem\u003E中\u003C\u002Fem\u003E列的宽度设置不正确,而且主内容区域的宽度设置也不正确,不过最终我们还是顽强的修复了IE6下的这个BUG:\n\t\t 在MasterPage的onReady函数\u003Cem\u003E中\u003C\u002Fem\u003E,首先修正内容区域的宽度(region3.setWidth(pageLayout1.getSize().width - region2.getSize().width - 5);region3.doLayout();),然后修正页面\u003Cem\u003E中\u003C\u002Fem\u003E所有表单的宽度(box_fixFormWidthInIE6();):\n\t\t 示例在 Site.Master 页面。\n\t+集成的AspNetAjax有一个很大的BUG,只要你在页面上进行过ajax操作,当改变窗口大小时你会惊讶的发现内容区域的内容全部为空了![fixed]\n\t\t-解决方法相当怪异,经过一个下午的不断尝试,终于用一个怪异的方法解决(box.{0}.setSize(box.{0}.getSize());box.{0}.doLayout();),\n\t\t 这样的代码让我想起刷新窗口时那个方法(window.location.href=window.location.href;),不管怎么说,我对能很好的解决这个重大的BUG很是欣喜。\n\t\n\t\n\t\n+2008-07-14 v0.3 beta6\n\t-增加FlashObject控件。[fixed]\n\t-PageLoading增加EnableFadeOut属性(默认false),可以启用淡出效果。[fixed]\n\t-Accordion选\u003Cem\u003E中\u003C\u002Fem\u003E样式微调。[fixed]\n\t-预加载Form表单出错时提示信息的背景图片。[fixed]\n\t+Grid增加EnableDelayRender属性(默认false),可以加快页面的渲染速度(一个典型的20个记录的页面,可提前0.7s-1s\u003Cem\u003E显示\u003C\u002Fem\u003E出来)。[fixed]\n\t\t-因为延迟加载\u003Cem\u003E数据\u003C\u002Fem\u003E不会改变Grid的大小,所以对于非布局内或不设定高度宽度的Grid,需要设置\"EnableDelayRender=false\"。\n\t-改变Grid\u003Cem\u003E中\u003C\u002Fem\u003E静态的CheckBoxField图片。[fixed]\n\t-TabStrip增加TabIndexChanged事件,同时Tab增加EnablePostBack,可以在点击一个Tab时引起回发事件。这在延迟加载Tab的内容非常有用。(示例在tabstrip.aspx)[fixed]\n\t\n\t\n\t\n+2008-07-12 v0.3 beta5\n\t-页面菜单Toolbar的分割符和背景不相融合。[fixed]\n\t-表单字段之间可以比较大小,比如NumberBox可以和Label比较大小,同时增加CompareType,来指定比较的类型(示例在form_compare.aspx)。[fixed]\n\t\t-如果是同种类型的表单字段,不需要指定CompareType,比如两个NumberBox比较值的大小不需要指定CompareType,而一个NumberBox和TextBox比较大小需要指定CompareType。\n\t+如果在编辑页面使用AspNetAjax,则不能在回发时关闭当前窗口[feedback:huihuang](示例在ajax_editor_main.aspx\u002Fajax_editor.aspx)。[fixed]\n\t\t-这是由于ajax后执行的javascript\u003Cem\u003E中\u003C\u002Fem\u003E不能有return false语句。\n\t+在文本框失去焦点时,执行一些Javascript脚本(示例在textbox_blur.aspx) [feedback:xmzhu]。[fixed]\n\t\t-在页面添加onReady函数(会被系统调用),然后用javascript监视文本框值的改变。\n\t-弹出Window默认\u003Cem\u003E显示\u003C\u002Fem\u003E的错误页面,解决方法在当前目录添加一个空的html页面,然后把Window控件的IFrameUrl指向这个页面而不是\"#\"。[fixed]\n\t+弹出的窗口\u003Cem\u003E中\u003C\u002Fem\u003E的弹出窗口的如果内容发生变化,则点击右上角的关闭按钮时会有提示用户先保存的对话框,但是这个对话框的被第二个弹出窗口覆盖了 [feedback:xmzhu]。[fixed]\n\t\t-原来的调用方法太麻烦(见示例\u003Cem\u003E中\u003C\u002Fem\u003Ealert\\alert_1.aspx和alert\\alert_2.aspx,总计 6 行代码),现在只需要 3 行代码就OK了。\n\t-点击提交按钮后变成灰色不可再次点击(示例在button_click_gray.aspx)[feedback:jima]。[fixed]\n\t+增加Menu、MenuText、MenuSeparator、MenuButton、MenuHyperLink控件,用于按钮的下拉菜单(示例在button_menu.aspx)。[fixed]\n\t-增加SplitButton控件。[fixed]\n\t\n\t\n\t\n+2008-07-09 v0.3 beta4\n\t-DataPicker默认的日期格式为(yyyy-MM-dd)。[fixed]\n\t+Form表单字段(TextBox,DropDownList...)之间可以比较大小 [feedback:huihuang]。[fixed]\n\t\t-增加ControlToCompare\u002FValueToCompare\u002FCompareOperator\u002FCompareMessage四个属性,示例在form_compare.aspx。\n\t+TabStrip\u003Cem\u003E中\u003C\u002Fem\u003E放置IFrame会出现渲染错误 (示例在tabstrip_iframe.aspx)[feedback:jima]。[fixed]\n\t\t-特殊处理,拥有IFrame的Tab如果不是激活Tab,则不设置Url,只有在激活时才设置Url。\n\t-RadioButtonList增加AutoPostBack属性(示例在radio.aspx) [feedback:xmzhu]。[fixed]\n\t-FormRow可以设置各列的宽度百分比 (示例在form_columnwidths.aspx)[feedback:jima]。[fixed]\n\t+表单字段Enable=false时\u003Cem\u003E显示\u003C\u002Fem\u003E颜色太浅 [feedback:jima]。[fixed]\n\t\t-覆盖缺省样式的.x-item-disabled,设置不透明。\n\t\n\t\n\t\n+2008-07-08 v0.3 beta3\n\t-Grid没有\u003Cem\u003E数据\u003C\u002Fem\u003E,向后翻页按钮可以点击的BUG [feedback:huihuang]。[fixed]\n\t+增加HiddenField控件。[fixed]\n\t\t-其实用TextBox也能模拟HiddenField的行为,只需要设置CssStyle=\"display:none;\"即可。\n\t+TriggerBox 如果 EnableTextBox = true,则不能将Text回发(这是html的限制)。[fixed]\n\t\t-最后的解决方案居然是设置 readonly=true,同时更改属性为 Readonly(示例在textbox2.aspx)。\n\t-模拟树的下拉列表在失去焦点后\u003Cem\u003E显示\u003C\u002Fem\u003E的文字不对的BUG。[fixed]\n\t+控制下拉列表某些项不可以选择(示例在dropdownlist2.aspx)。[fixed]\n\t\t-增加 DataEnableSelectField 属性,不可选择的项变灰,并且鼠标经过时没有样式。\n\t-LinkButton和Grid的LinkButtonField增加Enable属性(示例在hyperlink.aspx和grid.aspx)。[fixed]\n\t\n\t\n\t\n+2008-07-07 v0.3 beta2\n\t+增加UpdatePanelConnector控件,支持在布局构建的页面使用Asp.net Ajax。[fixed]\n\t\t-使用UpdatePanelConnector有一个要求:ContentTemplate下只能有一个子节点,比如box:Panel。\n\t\t-示例在ajax3.aspx\u002Fcontent_page4.aspx。\n\t\t-示例content_page3.aspx\u003Cem\u003E中\u003C\u002Fem\u003E,点击“Ajax查询”按钮和关闭弹出的窗口(点击右上角的叉)都引发异步更新。\n\t \n\t \n\t\n+2008-07-03 v0.3 beta1\n\t+容器控件的AutoHeight\u002FAutoWidth默认为false。[fixed]\n\t\t-使用GroupPanel的地方需要手工添加AutoHeight=\"true\"属性。\n\t+增加UserControlConnector,可以在其\u003Cem\u003E中\u003C\u002Fem\u003E放置用户控件(示例在page_usercontrol.aspx)。[fixed]\n\t\t-也可以在ContentPanel\u003Cem\u003E中\u003C\u002Fem\u003E放置用户控件,注意两者的区别。\n\t+增加ContentPlaceHolderConnector,替换原来Region的ContentPlaceHolderId属性(示例在Site.master)。[fixed]\n\t+支持Asp.net ajax异步加载。[fixed]\n\t\t-有很大局限性,只能在ContentPanel\u003Cem\u003E中\u003C\u002Fem\u003E使用,示例在ajax1.aspx\u002Fcontent_ajax2.aspx\u003Cem\u003E中\u003C\u002Fem\u003E。\n\t\t-对于使用布局构建的页面(比如content_page1.aspx)还不能使用Asp.net ajax,因为页面是整体渲染的,先放弃。\n\t\n\t\n\t\n+2008-07-02 v0.2 beta12\n\t+关闭前提示当前页面已经被修改(示例在content_page1.aspx\u002Fsimpleform.aspx)[fixed]\n\t\t-支持Iframe内按钮和window右上角关闭按钮。\n\t\t-删除CloseAction属性,可以在后台通过OnClientCloseButtonClick属性指定(为了和iframe\u003Cem\u003E中\u003C\u002Fem\u003E做法一致)。\n\t+iframe\u003Cem\u003E中\u003C\u002Fem\u003E的alert\u002Fconfirm要覆盖整个父页面,而不仅仅是iframe页面。[fixed]\n\t\t-在Firefox下还有问题。[fix pending]\n\t+排序时在标题栏\u003Cem\u003E显示\u003C\u002Fem\u003E排序箭头,可以排序的列标题光标为手形(示例在grid_sorting.aspx)。[fixed]\n\t\t-可以通过设置Grid1.CurrentSortColumnIndex = 0;来强制某列\u003Cem\u003E显示\u003C\u002Fem\u003E排序箭头。\n\t\t-可以通过 Grid1.Columns[Grid1.CurrentSortColumnIndex].SortExpression 的方式取得当前Grid的排序表达式。\n\t+HyperLinkField\u002FWindowField的链接地址支持服务器端格式(即是~\u002Falert.aspx)。[fixed]\n\t-TabStrip的Tab\u003Cem\u003E中\u003C\u002Fem\u003E如果放置ContentPanel,则内容渲染位置不正确。[fixed]\n\t-可以在ContentPanel\u003Cem\u003E中\u003C\u002Fem\u003E放置用户控件(示例在page_usercontrol.aspx)。[fixed]\n\t\t\n\t\n\t\n+2008-06-30 v0.2 beta11\n\t-增加TwinTriggerBox控件(示例在twintriggerbox.aspx)。[fixed]\n\t-Grid的\u003Cem\u003E数据\u003C\u002Fem\u003E库分页需要增加属性IsDatabasePaging=true,以便普通分页和\u003Cem\u003E数据\u003C\u002Fem\u003E库分页,否则在添加删除记录时总记录数不会变化 [feedback:zgjiang2]。[fixed]\n\t-关闭Window时PostBack事件OnClose可以指定参数,来区分是哪些操作引发的PostBack事件 [feedback:zgjiang2](示例在window_postback.aspx)。[fixed]\n\t-如果表单验证不通过,则需要弹出对话框提示(第一个没通过验证的字段)(目前还不能切换到相应的tab)。[fixed]\n\t+页面\u003Cem\u003E中\u003C\u002Fem\u003E任意可输入表单字段发生变化,可提示先保存。(示例在content_page1.aspx\u002Fsimpleform.aspx)[fixed]\n\t\t-目前还不支持Window右上角关闭按钮的提示保存功能。\n\t-Master\u002FContent的内容页\u003Cem\u003E中\u003C\u002Fem\u003EGrid的Sort事件不起作用的BUG [feedback:zgjiang2]。[fixed]\n\t-Grid\u003Cem\u003E中\u003C\u002Fem\u003E的LinkButtonField设置ConfirmText会出错 [feedback:huihuang]。[fixed]\n\t-增加静态类Confirm。[fixed]\n\t\n\t\n\t\n+2008-06-27 v0.2 beta10\n\t+Grid完善。[fixed]\n\t\t-CheckBoxField在回发时不能保持状态的BUG (已经更新了grid_checkboxfield.aspx示例)。\n\t\t-Grid\u003Cem\u003E中\u003C\u002Fem\u003E模拟树\u003Cem\u003E显示\u003C\u002Fem\u003E,GridColumn增加DataSimulateTreeLevelField属性(一个Grid只能有一个Column指定此属性),指定此列模拟树\u003Cem\u003E显示\u003C\u002Fem\u003E时的层次字段(0,1,2,...)(示例在grid_simulate_tree.aspx)。\n\t\t-切换分页时清空选\u003Cem\u003E中\u003C\u002Fem\u003E的值 [feedback:jqpeng]。\n\t\t-增加PreRowDataBound事件,可以在\u003Cem\u003E数据\u003C\u002Fem\u003E绑定之前设置某列的属性 [feedback:xmzhu] (示例在grid_prerowdatabound.aspx)。\n\t-DropDownList模拟树的方式\u003Cem\u003E显示\u003C\u002Fem\u003E,增加DataSimulateTreeLevelField属性,使用方法和Grid的类似(示例在dropdownlist_simulate_tree.aspx)。\n\t\n\t\n\t\n+2008-06-25 v0.2 beta9\n\t+Window窗体\u003Cem\u003E中\u003C\u002Fem\u003E的Iframe只让内容区域滚动,而Toolbar不滚动的规则。(示例在content_page2.aspx\u002Fsimpleform.aspx)[fixed]\n\t\t-在simpleform.aspx\u003Cem\u003E中\u003C\u002Fem\u003E:Panel[BodyPadding=5](Toolbar,Panel[Height=450 Layout=Fit](SimpleForm[AutoScroll=true])),则外面窗口的高度=450 + 5*2 + 26 + 32,其\u003Cem\u003E中\u003C\u002Fem\u003E26是Toolbar的高度,32是窗口的标题栏和下边框的高度。\n\t+关闭Iframe的LoadMask,所以需要Iframe页面添加PageLoading控件,这样效果统一。[fixed]\n\t+Grid完善。\n\t\t-去除EnableClientPaging和EnableClientSort属性,客户端排序和客户端分页在ASP.NET应用\u003Cem\u003E中\u003C\u002Fem\u003E会有很多问题(主要是状态保持的问题)。\n\t\t+EnableServerSort改名AllowSorting。(示例在grid_sorting.aspx)\n\t\t\t-使用非常简单:设置AllowSorting=true,注册OnSort事件,在事件处理函数\u003Cem\u003E中\u003C\u002Fem\u003E重新绑定\u003Cem\u003E数据\u003C\u002Fem\u003E。\n\t\t+增加AllowPaging属性。(示例在grid_paging.aspx)\n\t\t\t-使用非常简单:设置AllowPaging=true,PageSize=3,注册OnPageIndexChange事件,在事件处理函数\u003Cem\u003E中\u003C\u002Fem\u003EGrid1.PageIndex = e.NewPageIndex;OK。\n\t\t+\u003Cem\u003E数据\u003C\u002Fem\u003E库分页支持。(示例在grid_database_paging.aspx)\n\t\t\t-使用也非常简单:设置AllowPaging=true,PageSize=3,在绑定时设置RecordCount为总的记录数,在OnPageIndexChange事件处理函数\u003Cem\u003E中\u003C\u002Fem\u003EGrid1.PageIn","createTime":"2010-04-01 09:41:27","dataReportQuery":"spm=1035.2023.3001.6557&utm_medium=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-2-2190657-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default&depth_1-utm_source=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-2-2190657-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default","dataReportClick":"{\"mod\":\"popu_645\",\"index\":\"2\",\"dest\":\"https:\u002F\u002Fdownload.csdn.net\u002Fdownload\u002Fsuper_zhaowenke\u002F2190657\",\"strategy\":\"2~default~OPENSEARCH~Rate\",\"extra\":\"{\\\"utm_medium\\\":\\\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-2-2190657-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\\\",\\\"dist_request_id\\\":\\\"1713920331325_95453\\\"}\",\"spm\":\"1035.2023.3001.6557\"}","dataReportView":"{\"mod\":\"popu_645\",\"index\":\"2\",\"dest\":\"https:\u002F\u002Fdownload.csdn.net\u002Fdownload\u002Fsuper_zhaowenke\u002F2190657\",\"strategy\":\"2~default~OPENSEARCH~Rate\",\"extra\":\"{\\\"utm_medium\\\":\\\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-2-2190657-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\\\",\\\"dist_request_id\\\":\\\"1713920331325_95453\\\"}\",\"spm\":\"1035.2023.3001.6557\"}","type":"download"},{"url":"https:\u002F\u002Fdownload.csdn.net\u002Fdownload\u002Fsis_ying\u002F477425","title":"C#编程经验技巧宝典","desc":"C#编程经验技巧宝典源代码,目录如下:第1章 开发环境 11.1 Visual Studio开发环境安装与配置 20001 安装Visual Studio 2005开发环境须知 20002 配置合适的Visual Studio 2005开发环境 20003 设置程序代码行序号 30004 开发环境全屏\u003Cem\u003E显示\u003C\u002Fem\u003E 30005 设置窗口的自动隐藏功能 30006 根据需要创建所需解决方案 40007 如何使用“验证的目标架构”功能 41.2 Visual Studio开发环境的使用 40008 为程序设置版本和帮助信息 40009 设置Windows应用程序启动窗体 50010 设置\u003Cem\u003EWeb\u003C\u002Fem\u003E应用程序起始页 50011 如何设置程序的出错窗口 50012 如何进行程序调试 60013 如何结束不能正常运行的程序 60014 如何锁定窗体\u003Cem\u003E中\u003C\u002Fem\u003E的控件 60015 统一窗体\u003Cem\u003E中\u003C\u002Fem\u003E控件的字体设置 70016 通过“格式”菜单布局窗体 70017 起始页\u003Cem\u003E中\u003C\u002Fem\u003E的“Visual Studio开发人员新闻” 71.3 MSDN帮助的使用 80018 有效利用Visual Studio 2005附带程序 80019 有效使用MSDN帮助 90020 如何设置MSDN帮助 91.4 其他 100021 如何添加项目引用 100022 如何添加\u003Cem\u003EWeb\u003C\u002Fem\u003E引用 100023 如何添加引用第3方控件 110024 如何生成DLL文件 110025 如何使用不安全代码 11第2章 语言基础 132.1 注释 140026 如何对代码进行注释 140027 #region、#endregion关键字的使用技巧 140028 “\u002F\u002F\u002F”符号的使用技巧 140029 使用注释取消程序语句的执行 152.2 语句 150030 跳转语句GOTO的使用 150031 Continue语句的使用 160032 Break语句的使用 160033 Return语句的使用 170034 如何实现无限循环 170035 巧用foreach语句控制控件 180036 有效使用switch case语句 182.3 运算符 190037 如何使用引号赋值 190038 巧用“^=”运算符 190039 巧用位移运算符 200040 使用条件运算符 200041 巧用分隔符 200042 如何处理转义字符 210043 “;”结束符问题 210044 如何使用“??”操作符 222.4 表达式与关键词 220045 正确使用“&&”和“||” 220046 如何处理程序“溢出”错误 230047 有效使用base关键字 230048 typeof表达式的使用 230049 params关键字可以指定多参数 240050 using关键字的用法 240051 变量的作用域 252.5 其他 260052 有效使用this对象 260053 如何声明变量 260054 如何声明相同类型的多个变量 260055 利用Object变量传递参数 270056 强行改变运算符的运算顺序 27第3章 程序算法 293.1 \u003Cem\u003E数据\u003C\u002Fem\u003E结构 300057 如何实现单向链表 300058 如何实现双向链表 350059 如何实现堆栈 410060 队列的实现 430061 树的实现 443.2 排序 480062 如何实现选择排序算法 480063 如何实现冒泡排序算法 490064 如何实现快速排序算法 500065 如何实现插入排序算法 500066 如何实现希尔排序算法 513.3 常见算法的实际应用 520067 计算1+22+33+44+……+nn的值 520068 计算10!的值 520069 求最大公约数 520070 求最小公倍数 530071 判断素数的算法 530072 如何判断一个数是否是完数 540073 歌德巴赫猜想的算法 540074 八皇后问题 540075 用回溯法找出n个自然数\u003Cem\u003E中\u003C\u002Fem\u003E取r个数的全排列 550076 约瑟夫环问题 560077 猴子选大王 570078 如何判断IP是否正确 570079 如何将小写金额转换为大写金额 570080 统计文本字数 580081 文本\u003Cem\u003E中\u003C\u002Fem\u003E首字母改为大写 590082 C#随机数的产生 590083 身份证从15位升至18位算法 600084 十进制数转二进制数的算法 600085 十进制数转八进制数的算法 610086 十进制数转十六进制数的算法 620087 二、八、十六进制数转十进制数的算法 633.4 密码算法 650088 使用MD5算法对密码进行加密 650089 “凯撒”密码的算法 65第4章 字符及字符串处理技术 674.1 字符及字符串转换 680090 如何获得字母的ASCII码 680091 如何根据ASCII码获得字母 680092 编程\u003Cem\u003E中\u003C\u002Fem\u003E经常使用的ASCII码 680093 获得汉字的区位码 690094 如何根据区位码获得汉字 690095 如何将行字符串转换为列字符串 700096 如何将数字转换为字符串 700097 如何将字符串转换为数字 700098 如何将数字转换为日期格式 710099 如何将数字转换为货币格式 710100 将字母全部转换大写 710101 将字母全部转换小写 720102 将字符串首字母转换大写 720103 如何进行字节数组和字符串的相互转换 720104 如何把一个按空格分割的字符串存储在一个ArrayList数组\u003Cem\u003E中\u003C\u002Fem\u003E 734.2 获取字符串信息 730105 如何获得一个字符串的长度 730106 如何获得一个字符串\u003Cem\u003E中\u003C\u002Fem\u003E数字的长度 740107 如何获得字符串\u003Cem\u003E中\u003C\u002Fem\u003E数字或字母的长度 740108 如何获得字符串\u003Cem\u003E中\u003C\u002Fem\u003E某个数字的位置 750109 获得字符串\u003Cem\u003E中\u003C\u002Fem\u003E汉字的个数 760110 获得字符串\u003Cem\u003E中\u003C\u002Fem\u003E指定后几位字符 760111 计算字符串\u003Cem\u003E中\u003C\u002Fem\u003E子字符串出现的次数 760112 获得字符串\u003Cem\u003E中\u003C\u002Fem\u003E大写字母的个数 770113 获得某字符在字符串\u003Cem\u003E中\u003C\u002Fem\u003E最后出现的位置 780114 如何找出字符串\u003Cem\u003E中\u003C\u002Fem\u003E某一字符的所有位置 784.3 常用字符及字符串处理技术 790115 如何判断是否为数字 790116 如何在字符串\u003Cem\u003E中\u003C\u002Fem\u003E查找指定字符 790117 如何在字符串\u003Cem\u003E中\u003C\u002Fem\u003E用一子串替换另一子串 800118 将新字符串添加到已有字符串\u003Cem\u003E中\u003C\u002Fem\u003E 800119 如何在字符串\u003Cem\u003E中\u003C\u002Fem\u003E添加多个空格 810120 如何根据标点符号分行 810121 如何将字符串颠倒输出 820122 如何设置小数的保留位数 820123 如何对字符串进行组合或分解 820124 判断字符串\u003Cem\u003E中\u003C\u002Fem\u003E某一字符是否大写 830125 按要求生成指定位数编号 830126 确定两字符串是否相等 840127 判断两字符串\u003Cem\u003E中\u003C\u002Fem\u003E指定子串是否相等 840128 判断字符串是否为日期格式 850129 清除字符串\u003Cem\u003E中\u003C\u002Fem\u003E指定的字符 850130 复制字符串\u003Cem\u003E中\u003C\u002Fem\u003E指定的字符 850131 巧截字符串的数字 860132 如何存储变长字符串 860133 在进行字符串比较时忽略大小写 870134 如何去除字符串尾空格 870135 如何去掉字符串\u003Cem\u003E中\u003C\u002Fem\u003E所有空格 880136 如何进行文本加密与解密 880137 如何区别0、空字符串、Null、Empty和Nothing 890138 从字符串\u003Cem\u003E中\u003C\u002Fem\u003E分离文件路径、文件名及扩展名 890139 如何批量替换某一类字符串 89第5章 \u003Cem\u003E数据\u003C\u002Fem\u003E处理 915.1 数字处理技巧 920140 如何对计算结果四舍五放入 920141 如何将商品金额小写转换成大写 920142 如何根据生日自动计算员工年龄 930143 如何设置货币值\u003Cem\u003E中\u003C\u002Fem\u003E使用的小数位数 930144 如何自定义货币值\u003Cem\u003E中\u003C\u002Fem\u003E的小数点 940145 如何自定义货币值\u003Cem\u003E中\u003C\u002Fem\u003E小数点左边数字分组字符 940146 如何自定义货币值\u003Cem\u003E中\u003C\u002Fem\u003E小数点左边每一组的位数 950147 如何自定义百分比值\u003Cem\u003E中\u003C\u002Fem\u003E小数的位数 950148 如何自定义百分比小数点 960149 如何自定义百分比小数点左边数字分组字符 960150 如何自定义百分比小数点左边每一组的位数 970151 如何自定义百分比符号 970152 如何自定义数字小数点右边的保留位数 980153 如何自定义数字小数点左边分组位数 980154 格式化输入\u003Cem\u003E数据\u003C\u002Fem\u003E为货币格式 990155 如何计算两个整数的乘积 990156 如何将二进制数转换为十进制数 1000157 如何将二进制数转换为八进制数 1000158 如何将二进制数转换为十六进制数 1000159 如何实现0~9之间随机整数 1010160 如何实现0~1之间随机数 1010161 如何返回数字的绝对值 1015.2 控件\u003Cem\u003E数据\u003C\u002Fem\u003E处理技巧 1020162 如何实现C#\u003Cem\u003E中\u003C\u002Fem\u003E用键完成TAB的功能 1020163 如何限制文本框密码输入长度 1020164 \u003Cem\u003E数据\u003C\u002Fem\u003E输入为空提示 1030165 如何设置文本框光标到末尾 1030166 输入法调整技巧 1030167 锁定文本框内的文本 1030168 使用Message.Show输出用户信息 1045.3 图片\u003Cem\u003E数据\u003C\u002Fem\u003E处理技巧 1040169 如何将图片存入\u003Cem\u003E数据\u003C\u002Fem\u003E库 1040170 如何将图片从\u003Cem\u003E数据\u003C\u002Fem\u003E库\u003Cem\u003E中\u003C\u002Fem\u003E读取出来 1040171 如何只允许输入指定图片格式 1050172 如何设置录入图片统一图片大小 1055.4 数组处理技巧 1050173 如何转换数组类型 1050174 如何复制数组\u003Cem\u003E中\u003C\u002Fem\u003E一系列元素的元素 1060175 如何检索指定条件数组\u003Cem\u003E中\u003C\u002Fem\u003E的元素 1070176 如何动态改变数组长度 1080177 如何反转数组\u003Cem\u003E中\u003C\u002Fem\u003E元素的顺序 1080178 如何排序数组\u003Cem\u003E中\u003C\u002Fem\u003E的元素的顺序 1090179 如何创建动态数组 1105.5 NET应用技巧 1100180 如何使用ASP.NET技术对口令加密 1100181 如何设定ASP.NET全局变量 1110182 如何设定全局联接\u003Cem\u003E数据\u003C\u002Fem\u003E库对象 1110183 如何在ASP.NET\u003Cem\u003E中\u003C\u002Fem\u003E获得客户端IP地址 1110184 如何在ASP.NET\u003Cem\u003E中\u003C\u002Fem\u003E获取文件的扩展名 1110185 如何在ASP.NET\u003Cem\u003E中\u003C\u002Fem\u003E用URL在页面之间传值 1120186 如何使用IsPostBack实现ASP.NET页面加载 1120187 如何利用输出缓存技术缓存ASP.NET页面 1120188 如何在ASP.NET\u003Cem\u003E中\u003C\u002Fem\u003E\u003Cem\u003E显示\u003C\u002Fem\u003E当前IE浏览器头信息 1135.6 其他应用技巧 1140189 如何判断年份是否为闰年 1140190 如何根据年份判断十二生肖 1140191 如何根据IP地址获取本机域名 1150192 如何获取“我的文档”系统文件夹路径 1150193 如何获取应用程序当前执行的路径 1160194 如何获取当前操作系统的信息 1160195 如何实现基本\u003Cem\u003E数据\u003C\u002Fem\u003E类型随意转换 1160196 如何生成全局唯一标识符(GUID) 118第6章 资料验证技术 1196.1 网络验证应用技巧 1200197 如何使用正则表达式验证E-mail格式 1200198 如何使用正则表达式验证IP地址 1200199 如何使用正则表达式验证URL 1206.2 常用数字验证技巧 1210200 如何使用正则表达式验证电话号码 1210201 如何使用正则表达式验证输入密码条件 1210202 如何使用正则表达式验证邮政编号 1210203 如何使用正则表达式验证手机号 1220204 如何使用正则表达式验证身份证号 1220205 如何使用正则表达式验证两位小数 1220206 如何使用正则表达式验证一年的12个月份 1230207 如何使用正则表达式验证一个月的31天 1230208 如何使用正则表达式验证数字输入 1230209 如何使用正则表达式验证密码长度 1240210 如何使用正则表达式验证非零的正整数 1240211 如何使用正则表达式验证非零的负整数 1246.3 常用字符验证技巧 1250212 如何使用正则表达式验证大写字母 1250213 如何使用正则表达式验证小写字母 1250214 使用正则表达式检查字符串\u003Cem\u003E中\u003C\u002Fem\u003E重复出现的词 1250215 如何使用正则表达式替换字符串 1260216 如何使用正则表达式拆分字符串 1270217 如何使用正则表达式验证输入字母 1270218 如何使用正则表达式验证\u003Cem\u003E中\u003C\u002Fem\u003E文汉字输入 1280219 如何使用正则表达式验证输入字符串 128第7章 日期和时间 1297.1 日期与时间的获取 1300220 获得系统当前日期 1300221 获得系统当前时间 1300222 同时获得系统当前日期和时间 1300223 如何获取当前日期是星期几 1300224 如何获取当前年的天数 1310225 如何获取当前月的天数 1310226 如何取得当前日期的前一天 1320227 使用TimeSpan对象获取时间间隔 1337.2 日期的格式化及其时间的比较 1330228 将日期格式化为指定格式 1330229 如何将短日期格式化为长日期格式 1340230 如何将数字日期转化为\u003Cem\u003E中\u003C\u002Fem\u003E文格式 1340231 如何对系统时间和数字进行比较 1350232 如何比较时间 1350233 获取两个日期之间的时间差并进行比较 1367.3 日期方法与函数的应用 1360234 使用DateDiff方法获取日期时间的间隔数 1360235 在SQL语句\u003Cem\u003E中\u003C\u002Fem\u003E使用DATEADD函数向指定日期添加一段时间间隔 1370236 在SQL语句\u003Cem\u003E中\u003C\u002Fem\u003E使用DATEDIFF函数获得两个日期的间隔 1370237 如何使用Sleep方法延迟时间 1370238 如何确定程序的运行时间 1380239 如何使用ParseExact方法将字符串转化为日期格式 1380240 如何使用ToString方法格式化日期 1390241 如何使用Convert方法转换日期\u003Cem\u003E显示\u003C\u002Fem\u003E格式 1397.4 系统时间与日期的设置 1400242 如何设置系统的日期 1400243 如何设置系统的时间 1400244 如何设置系统的日期和时间 1417.5 日期与时间的应用 1420245 如何将\u003Cem\u003E数据\u003C\u002Fem\u003E控件\u003Cem\u003E中\u003C\u002Fem\u003E的日期以编程的方式转化为指定格式 1420246 将格式化日期的方法绑定到\u003Cem\u003E数据\u003C\u002Fem\u003E控件\u003Cem\u003E中\u003C\u002Fem\u003E 1420247 直接格式化绑定到\u003Cem\u003E数据\u003C\u002Fem\u003E控件GridView\u003Cem\u003E中\u003C\u002Fem\u003E的日期列 1430248 在\u003Cem\u003E数据\u003C\u002Fem\u003E控件GridView的RowDataBound事件\u003Cem\u003E中\u003C\u002Fem\u003E对绑定到GridView控件的日期列进行格式化 1430249 如何实现倒计时功能 1430250 如何创建一个数字时钟 144第8章 Windows窗体设计 1458.1 Windows窗体基本操作 1460251 控制窗体加载时所在的位置 1460252 控制窗体最大化、最小化 1460253 清空窗体\u003Cem\u003E中\u003C\u002Fem\u003E的图片 1460254 如何使程序窗体总在最前 1470255 如何将菜单置于窗体的左侧 1470256 将其他窗体作为当前窗体的子窗体 1470257 如何根据控件大小自动\u003Cem\u003E显示\u003C\u002Fem\u003E滚动条 1480258 如何\u003Cem\u003E显示\u003C\u002Fem\u003EAbout窗体 1480259 利用Show方法\u003Cem\u003E显示\u003C\u002Fem\u003E被调用窗体 1490260 Load事件将窗体加载到内存 1490261 窗体的卸载与隐藏 1490262 设置窗体的状态 1490263 如何设置窗体在桌面上的位置 1500264 如何在关闭窗体前\u003Cem\u003E显示\u003C\u002Fem\u003E确认对话框 1500265 如何去掉窗体的标题栏 1510266 如何禁止在任务栏\u003Cem\u003E中\u003C\u002Fem\u003E\u003Cem\u003E显示\u003C\u002Fem\u003E窗体标题 1520267 如何禁止缩放窗体的边框 1520268 如何设置窗体标题栏文字右对齐 1520269 如何\u003Cem\u003E显示\u003C\u002Fem\u003E窗体的属性信息 1530270 如何隐藏窗体标题栏的按钮 1538.2 Windows窗体高级操作 1530271 设置闪烁的标题栏 1530272 如何在托盘\u003Cem\u003E中\u003C\u002Fem\u003E写入应用程序图标 1540273 如何以全屏方式\u003Cem\u003E显示\u003C\u002Fem\u003E程序窗体 1540274 如何从上次关闭位置启动窗体 1540275 如何通过拖动工作区来移动窗体 1550276 如何渐变\u003Cem\u003E显示\u003C\u002Fem\u003E窗体背景颜色 1550277 如何排列MDI窗体\u003Cem\u003E中\u003C\u002Fem\u003E的子窗体 1560278 如何拖动无标题栏窗体 1578.3 特殊类型的窗体 1580279 创建一个无ICON的窗体 1580280 如何制作飘动的窗体 1580281 使用拆分窗口 1590282 用C#实现启动欢迎界面 1590283 如何实现半透明渐显窗体 1600284 基于ListView的导航界面 1600285 类似OutLook的导航界面 1620286 图形化的导航界面 1620287 如何实现类似QQ的程序界面 1620288 如何实现类似Windows XP的程序界面 1640289 制作字形窗体 1640290 制作图形窗体 1640291 随机更换背景的窗体 1658.4 菜单、工具栏和状态栏的设计 1660292 带图标的菜单 1660293 带历史信息的菜单 1660294 可以拉伸的菜单 1670295 带背景的工具栏 1680296 浮动工具栏 1680297 带下拉菜单的工具栏 1690298 在状态栏\u003Cem\u003E中\u003C\u002Fem\u003E\u003Cem\u003E显示\u003C\u002Fem\u003E复选框 1690299 带进度条的状态栏 1690300 带图标的状态栏 1708.5 其他 1700301 界面设计要素 1700302 界面设计在程序开发\u003Cem\u003E中\u003C\u002Fem\u003E的重要性 1710303 如何设置窗体的键响应按钮 1720304 如何设置窗体的键响应按钮 1720305 窗体间\u003Cem\u003E数据\u003C\u002Fem\u003E的访问 172第9章 Windows窗体控件 1759.1 TextBox控件应用技巧 1760306 文本框\u003Cem\u003E中\u003C\u002Fem\u003E只能输入数字 1760307 如何设置TextBox控件输入多行文本 1760308 如何锁定文本框 1760309 如何控制TextBox控件\u003Cem\u003E中\u003C\u002Fem\u003E的插入点 1760310 如何创建密码文本框 1770311 如何创建只读文本框 1770312 如何在文本框字符串\u003Cem\u003E中\u003C\u002Fem\u003E放置引号 1770313 如何在TextBox控件\u003Cem\u003E中\u003C\u002Fem\u003E查看多个行 1770314 如何TextBox控件\u003Cem\u003E中\u003C\u002Fem\u003E\u003Cem\u003E显示\u003C\u002Fem\u003E回车符 1789.2 RichTextBox控件应用技巧 1780315 删除RichTextBox控件\u003Cem\u003E中\u003C\u002Fem\u003E的部分文字 1780316 RichTextBox与TextBox控件有何不同 1790317 如何使用RichTextBox控件\u003Cem\u003E显示\u003C\u002Fem\u003E文件 1790318 如何使用RichTextBox控件保存文件 1800319 如何在RichTextBox控件\u003Cem\u003E中\u003C\u002Fem\u003E查找字符 1810320 如何在RichTextBox控件插入图片 1810321 如何为RichTextBox控件添加快捷菜单 1820322 在RichTextBox控件\u003Cem\u003E中\u003C\u002Fem\u003E替换文本文字 1839.3 Button控件应用技巧 1830323 C#\u003Cem\u003E中\u003C\u002Fem\u003E轻松打造绚丽按钮 1830324 如何使Button控件大小自动适应文本长度 1840325 如何设置窗体一个默认单击按钮 1840326 如何设置窗体一个默认取消按钮 1840327 如何给按钮控件创建快捷键 1850328 如何触发Button按钮的Click事件 1850329 使用控件的Tag属性传递信息 1850330 如何在Windows窗体上停靠控件 1860331 如何动态创建Button控件 1869.4 DataGridView控件应用技巧 1870332 如何对DataGridView控件进行\u003Cem\u003E数据\u003C\u002Fem\u003E绑定 1870333 如何在DataGridView控件\u003Cem\u003E中\u003C\u002Fem\u003E设置\u003Cem\u003E数据\u003C\u002Fem\u003E的格式 1870334 如何在DataGridView控件基于文本的单元格\u003Cem\u003E中\u003C\u002Fem\u003E启用换行 1870335 如何设置DataGridView控件单元格的文本对齐方式 1870336 如何在DataGridView控件\u003Cem\u003E中\u003C\u002Fem\u003E验证\u003Cem\u003E数据\u003C\u002Fem\u003E输入 1880337 DataGridView控件\u003Cem\u003E中\u003C\u002Fem\u003E输入\u003Cem\u003E数据\u003C\u002Fem\u003E时发生的错误 1880338 如何设置DataGridView控件\u003Cem\u003E中\u003C\u002Fem\u003E网格线的样式 1890339 如何设置DataGridView控件\u003Cem\u003E中\u003C\u002Fem\u003E的边框样式 1890340 如何设置DataGridView控件\u003Cem\u003E中\u003C\u002Fem\u003E字体样式 1900341 如何设置DataGridView控件\u003Cem\u003E中\u003C\u002Fem\u003E颜色样式 1900342 获取DataGridView控件\u003Cem\u003E中\u003C\u002Fem\u003E单元格、行和列坐标 1900343 如何获取DataGridView控件\u003Cem\u003E中\u003C\u002Fem\u003E的当前单元格 1910344 如何禁止DataGridView控件\u003Cem\u003E中\u003C\u002Fem\u003E添加和删除行 1910345 DataGridView控件选\u003Cem\u003E中\u003C\u002Fem\u003E单元格时整个行背景变色 1910346 如何复制DataGridView控件单元格\u003Cem\u003E中\u003C\u002Fem\u003E的\u003Cem\u003E数据\u003C\u002Fem\u003E 1910347 如何在DataGridView控件实现下拉列表 1929.5 对话框控件应用技巧 1920348 如何利用FontDialog控件设置字体 1920349 如何利用ColorDialog控件设置字颜色 1930350 如何利用OpenFileDialog控件打开文件 1930351 如何获得弹出对话框的相关返回值 1940352 使用FolderBrowserDialog控件选择文件夹 1959.6 ListBox控件应用技巧 1950353 如何快速选\u003Cem\u003E中\u003C\u002Fem\u003EListBox控件\u003Cem\u003E中\u003C\u002Fem\u003E全部条目 1950354 如何排序ListBox控件\u003Cem\u003E中\u003C\u002Fem\u003E的\u003Cem\u003E数据\u003C\u002Fem\u003E 1960355 如何实现ListBox控件的多项选择功能 1960356 如何在ListBox控件\u003Cem\u003E中\u003C\u002Fem\u003E查找指定的项 1960357 实现ListBox控件与ListBox控件交换\u003Cem\u003E数据\u003C\u002Fem\u003E 1979.7 ListView控件应用技巧 1980358 如何实现ListView控件实现动态加载\u003Cem\u003E数据\u003C\u002Fem\u003E 1980359 如何向ListView控件添加搜索功能 1990360 如何将\u003Cem\u003E数据\u003C\u002Fem\u003E\u003Cem\u003E中\u003C\u002Fem\u003E的表内容填充到ListView控件\u003Cem\u003E中\u003C\u002Fem\u003E 2000361 如何使ListView控件拥有编辑功能 2010362 如何实现ListView控件\u003Cem\u003E显示\u003C\u002Fem\u003E图标与列表 2010363 如何获取ListView控件\u003Cem\u003E中\u003C\u002Fem\u003E的选择结果 2020364 如何将图片加载ListView控件 2029.8 TreeView控件应用技巧 2030365 如何在TreeView控件结点\u003Cem\u003E中\u003C\u002Fem\u003E\u003Cem\u003E显示\u003C\u002Fem\u003E图片 2030366 如何在TreeView控件\u003Cem\u003E中\u003C\u002Fem\u003E用鼠标右键选\u003Cem\u003E中\u003C\u002Fem\u003E节点 2030367 区分TreeView控件选\u003Cem\u003E中\u003C\u002Fem\u003E各节点方式 2040368 如何实现TreeView控件节点拖放操作 2040369 如何实现带复选框的TtreeView控件 2050370 如何实现TreeView控件遍历磁盘目录 2060371 如何将\u003Cem\u003E数据\u003C\u002Fem\u003E库字段填充到TreeView控件 2069.9 ComboBox控件应用技巧 2070372 如何使ComboBox下拉列表\u003Cem\u003E显示\u003C\u002Fem\u003E图片 2070373 ComboBox只能从下拉列表框\u003Cem\u003E中\u003C\u002Fem\u003E选择\u003Cem\u003E数据\u003C\u002Fem\u003E 2080374 如何实现带查询功能的ComboBox控件 2080375 如何实现文件目录名称填充ComboBox控件 2090376 如何将数组绑定到ComboBox控件 2100377 如何将\u003Cem\u003E数据\u003C\u002Fem\u003E库字段绑定到ComboBox控件 2109.10 组件应用技巧 2110378 如何使用ProgressBar控件\u003Cem\u003E显示\u003C\u002Fem\u003E操作的进度 2110379 如何使用ToolTip控件\u003Cem\u003E显示\u003C\u002Fem\u003E提示信息 2110380 如何使用FlowLayoutPanel控件布局窗体 2120381 如何使用SplitContainer控件分隔窗体 2130382 如何使用Process组件打开系统进程 2140383 FileSystemWatcher监视文件夹内文件的更改 2149.11 其他常用件控件应用技巧 2150384 如何在状态栏\u003Cem\u003E中\u003C\u002Fem\u003E\u003Cem\u003E显示\u003C\u002Fem\u003E时间 2150385 如何在状态栏\u003Cem\u003E中\u003C\u002Fem\u003E加载图片 2150386 如何设置DateTimePicker控件\u003Cem\u003E显示\u003C\u002Fem\u003E为空文 2150387 如何判断ToolStrip控件Button控钮的单击 2150388 如何实现Panle自动调整大小充满窗体 2160389 如何实现CheckedListBox控件选重所有项 2160390 如何实现CheckBox控件的选择状态 2160391 如何使Lable控件\u003Cem\u003E显示\u003C\u002Fem\u003E出多行文字 2170392 如何使用LinkLabel控件实现超级链接 2170393 如何设置MaskedTextBox控件输入验证 2180394 如何使用NotifyIcon控件创建任务托盘 2190395 如何控制PictureBox控件\u003Cem\u003E显示\u003C\u002Fem\u003E图片风格 219第10章 \u003Cem\u003EWeb\u003C\u002Fem\u003E页面设计 22110.1 网页外观设计 2220396 将CSS样式表应用到页面\u003Cem\u003E中\u003C\u002Fem\u003E 2220397 在页面的源码\u003Cem\u003E中\u003C\u002Fem\u003E直接定义样式表 2220398 动态加载主题到页面\u003Cem\u003E中\u003C\u002Fem\u003E 2230399 利用Table布局\u003Cem\u003EWeb\u003C\u002Fem\u003E页面 2230400 FrameSet框架的应用 2240401 IFrame框架的应用 2240402 页面尺寸自动适应1024×768像素和800×600分辨率 22510.2 网页性能设计 2250403 用meta标签来增强网页性能 2250404 什么情况下使用缓冲会提高速度 2260405 使用OutputCache指令实现页面缓存 2260406 设置网页缓存的位置 2270407 使用Cache类实现应用程序\u003Cem\u003E数据\u003C\u002Fem\u003E缓存 2270408 缓存网页的不同版本 22710.3 \u003Cem\u003EWeb\u003C\u002Fem\u003E页的绑定 2280409 如何绑定变量 2280410 如何绑定集合 2280411 如何绑定表达式 2290412 如何绑定方法结果 2300413 巧用DataBinder.Eval()方法进行\u003Cem\u003E数据\u003C\u002Fem\u003E绑定 2300414 如何将DropDownList控件绑定到GridView控件\u003Cem\u003E中\u003C\u002Fem\u003E 23110.4 开发\u003Cem\u003EWeb\u003C\u002Fem\u003E页的常用功能 2310415 使用QueryString变量在页面之间传值 2310416 页面定时刷新如何实现 2320417 \u003Cem\u003E显示\u003C\u002Fem\u003E只有数字的验证码图片 2320418 \u003Cem\u003E显示\u003C\u002Fem\u003E数字和英文字母组合的验证码图片 2320419 页面定时刷新后跳转到其他页 2330420 打开新的窗口并传送参数 2330421 动态\u003Cem\u003E显示\u003C\u002Fem\u003E用户头像 2330422 利用Pannel控件\u003Cem\u003E显示\u003C\u002Fem\u003E和隐藏一组控件 2330423 如何在GridView控件上添加删除确认 2340424 如何为GridView控件添加编号列 2340425 FindControl方法的应用 2340426 如何实现单击表格行打开另一页并传递参数 2350427 如何实现双击表格行超级链接到另一页并传递参数 2350428 如何实现单击表格行改变颜色 2350429 鼠标移动改变表格行的颜色 2350430 如何在\u003Cem\u003EWeb\u003C\u002Fem\u003E页\u003Cem\u003E中\u003C\u002Fem\u003E使用表格控件 23610.5 \u003Cem\u003EWeb\u003C\u002Fem\u003E.Config文件的配置 2370431 通过Encoding的设置实现页面无乱码 2370432 限制上传文件大小与时间 2370433 配置验证级别 23710.6 开发\u003Cem\u003EWeb\u003C\u002Fem\u003E页其他功能 2380434 如何使Pannel实现横向滚动纵向自动扩展 2380435 属性MaintainScrollPositionOnPostBack实现网页定位 2380436 自动隐藏式菜单 2380437 关闭弹出窗口刷新父窗口 2390438 弹出网页模式对话框 2400439 弹出全屏\u003Cem\u003E显示\u003C\u002Fem\u003E网页 2410440 为什么要生成静态页 2420441 用快捷键+实现屏蔽 2420442 如何在\u003Cem\u003EWeb\u003C\u002Fem\u003E页\u003Cem\u003E中\u003C\u002Fem\u003E使用广告控件 2420443 滚动\u003Cem\u003E显示\u003C\u002Fem\u003E博客公告 243第11章 HTML客户端控件与服务器控件 24511.1 \u003Cem\u003E数据\u003C\u002Fem\u003E控件应用技巧 2460444 如何将数组绑定到GridView\u003Cem\u003E数据\u003C\u002Fem\u003E控件\u003Cem\u003E中\u003C\u002Fem\u003E 2460445 使用GridView \u003Cem\u003EWeb\u003C\u002Fem\u003E服务器控件绑定\u003Cem\u003E数据\u003C\u002Fem\u003E源 2460446 使用GridView \u003Cem\u003EWeb\u003C\u002Fem\u003E服务器控件自定义外观风格 2470447 使用GridView \u003Cem\u003EWeb\u003C\u002Fem\u003E服务器控件的简单排序 2470448 如何在GridView \u003Cem\u003EWeb\u003C\u002Fem\u003E服务器控件\u003Cem\u003E中\u003C\u002Fem\u003E分页 2480449 使用GridView \u003Cem\u003EWeb\u003C\u002Fem\u003E服务器控件编辑\u003Cem\u003E数据\u003C\u002Fem\u003E 2490450 使用GridView \u003Cem\u003EWeb\u003C\u002Fem\u003E服务器控件删除\u003Cem\u003E数据\u003C\u002Fem\u003E 2510451 如何使用GridView \u003Cem\u003EWeb\u003C\u002Fem\u003E服务器控件选择\u003Cem\u003E数据\u003C\u002Fem\u003E 2520452 单击GridView控件按钮刷新保持原来的位置 2530453 向GridView \u003Cem\u003EWeb\u003C\u002Fem\u003E控件\u003Cem\u003E中\u003C\u002Fem\u003E添加CheckBox控件 2530454 如何使用GridView \u003Cem\u003EWeb\u003C\u002Fem\u003E控件实现超级链接 2540455 在GridView \u003Cem\u003EWeb\u003C\u002Fem\u003E控件\u003Cem\u003E中\u003C\u002Fem\u003E高亮\u003Cem\u003E显示\u003C\u002Fem\u003E鼠标所在行 2560456 实现DataList \u003Cem\u003EWeb\u003C\u002Fem\u003E服务器控件\u003Cem\u003E数据\u003C\u002Fem\u003E绑定功能 2560457 如何实现DataList \u003Cem\u003EWeb\u003C\u002Fem\u003E服务器控件分页功能 2580458 实现查看DataList控件\u003Cem\u003E中\u003C\u002Fem\u003E\u003Cem\u003E数据\u003C\u002Fem\u003E的详细信息 2590459 如何在DataList控件\u003Cem\u003E中\u003C\u002Fem\u003E创建多个列 2600460 如何实现DetailsView 控件分页功能 2610461 将DataSet类对象绑定到Repeater\u003Cem\u003E数据\u003C\u002Fem\u003E控件\u003Cem\u003E中\u003C\u002Fem\u003E 26211.2 导航控件应用技巧 2630462 TreeView、SiteMapDataSource控件和SiteMap文件实现导航 2630463 如何在TreeView控件\u003Cem\u003E中\u003C\u002Fem\u003E添加连接线 2640464 以编程方式向TreeView控件\u003Cem\u003E中\u003C\u002Fem\u003E添加节点 2640465 如何在TreeView控件\u003Cem\u003E中\u003C\u002Fem\u003E\u003Cem\u003E显示\u003C\u002Fem\u003ECheckBox控件 2650466 如何判断TreeView控件\u003Cem\u003E中\u003C\u002Fem\u003E被勾选的节点 2650467 用SiteMapPath控件绑定SiteMap文件实现导航 2660468 如何设置SiteMapPath控件路径分隔符 2660469 如何设置SiteMapPath控件路径方向 2670470 如何设置SiteMapPath控件父节点\u003Cem\u003E显示\u003C\u002Fem\u003E个数 2670471 如何设置SiteMapPath控件提示字符 2680472 如何用Menu控件绑定SiteMap文件实现导航 2680473 如何设置Menu控件\u003Cem\u003E显示\u003C\u002Fem\u003E静态菜单 2690474 如何以编程方式创建Menu控件 27011.3 标准控件应用技巧 2710475 使用HyperLink服务器控件实现页面间传值 2710476 如何使用Input(Reset)实现文本框清空功能 2710477 如何取消DropDownLidt控件的激发验证 2720478 使用FileUpload服务器控件实现文件上传 2720479 使用LinkButton服务器控件实现超级链接 2730480 实现DropDownList服务器控件的\u003Cem\u003E数据\u003C\u002Fem\u003E绑定 2730481 如何改变DropDownList服务器控件\u003Cem\u003E中\u003C\u002Fem\u003E的项 2740482 指定ListBox服务器控件\u003Cem\u003E中\u003C\u002Fem\u003E的项的目的移位顺序 2750483 响应ListBox服务器控件的改变事件 2760484 如何使用CheckBox服务器控件 2760485 如何使用CheckBoxList服务器控件 2770486 使用RadioButtonList服务器控件巧用单项选择 2780487 使用BulletedList控件\u003Cem\u003E显示\u003C\u002Fem\u003E项目符号和编号 2790488 如何使用HiddenField控件 2800489 如何使用Literal控件\u003Cem\u003E显示\u003C\u002Fem\u003E静态文本 2810490 如何使用AdRotator控件制作广告 2810491 如何使用Wizard \u003Cem\u003EWeb\u003C\u002Fem\u003E服务器控件制作导航页 2820492 使用XML服务器控件转换XML文档 2830493 使用MultiView与View控件制作导航页面 2860494 使用PlaceHolder控件实现动态添加控件 2890495 如何实现带滚动条的Panel面板 2900496 使用Substitution控件在缓存页面插入内容 290第12章 内置对象 29312.1 ASP.NET基本对象 2940497 使用Session对象在页面之间传值 2940498 如何使用Session验证用户登录 2940499 配置Session的生命周期 2940500 如何遍历Session对象 2950501 使用Application对象在页面之间传值 2950502 存取Application变量内容 2950503 如何锁定Application对象 2960504 如何使用Application实现站点访问量统计 2960505 如何删除Application变量内容 2960506 使用ViewState对象在同一个页面传值 29712.2 Response与Request对象 2970507 如何解决Response.Redirect方法传递汉字时出现的错误 2970508 使用Response.BinaryWrite方法输出二进制图像 2970509 Response对象将文本文件的内容写回客户端浏览器 2980510 如何使用Request接收页面间传值 2980511 使用Request对象的Browser属性获取客户端浏览器信息 2980512 获取客户端和服务器端IP地址 2990513 使用Request对象获取客户端的表单信息 3000514 使用Request对象的PhysicalApplicationPath属性获取服务器的绝对路径 3000515 使用Request对象的CurrentExecutionFilePath属性获取当前页面的路径 3000516 如何获取ASP.NET\u003Cem\u003E中\u003C\u002Fem\u003E所有Request的属性 3000517 缓存区的应用 30112.3 Cookie对象 3020518 使用Cookie的优缺点 3020519 使用Cookie对象在页面之间传值 3020520 如何使用Cookie验证用户登录 3030521 Cookie可以存储哪些值 3030522 使用Cookie对象保存和读取客户端信息 3030523 如何加密Cookie\u003Cem\u003E中\u003C\u002Fem\u003E的\u003Cem\u003E数据\u003C\u002Fem\u003E 3040524 创建及存取多个键值的Cookie对象 3040525 如何遍历Cookie集合 3040526 设定Cookie变量的生命周期 3050527 如何删除客户端的Cookies 3050528 如何删除多值Cookie\u003Cem\u003E中\u003C\u002Fem\u003E的某个值 3050529 如何使用Cookie处理网上重复投票 3050530 如何使用户第2次访问我的网站不用提交信息 30612.4 Server对象 3070531 使用Server.Transfer方法在页面之间传值 3070532 使用Server.MapPath方法获取服务器的物理地址 3080533 使用Server.UrlEncode方法对字符串进行编码 3080534 使用Server.UrlDecode方法对字符串进行解码 3080535 利用Server对象进行HTML编码输出 3080536 利用Server对象进行HTML解码输出 309第13章 图形图像技术 31113.1 图像预览及转换 3120537 如何设计缩略图功能的图片浏览器 3120538 如何浏览大图片 3120539 如何局部放大图片 3130540 如何实现剪切图片 31313.2 图形缩放与变换 3150541 如何缩放图片 3150542 如何转换图像文件格式 31513.3 图像效果 3160543 如何以底片效果\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3160544 如何以浮雕效果\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3170545 如何以黑白效果\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3180546 如何以柔化效果\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3190547 如何以锐化效果\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3200548 如何以雾化效果\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3210549 如何以光照效果\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3220550 如何以百叶窗效果\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3230551 如何以马赛克效果\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3250552 如何以任意角度旋转图像 3260553 如何以椭圆形\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3270554 如何以不同的透明度\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3280555 如何以不同分辨率\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3280556 如何以不同翻转方式\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3290557 如何以油画效果\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3300558 如何以扭曲效果\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3310559 如何以分块效果\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3320560 如何以四周扩散方式\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3330561 如何以从上向下拉伸方式\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3340562 如何以从左向右拉伸方式\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3350563 如何以上下反转方式\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3350564 如何以上下对接方式\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3360565 如何以左右反转方式\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3370566 如何以左右对接方式\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3380567 如何以淡入淡出效果\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3390568 如何以积木效果\u003Cem\u003E显示\u003C\u002Fem\u003E图像 34113.4 图像字体 3420569 如何以渐变色效果\u003Cem\u003E显示\u003C\u002Fem\u003E文字 3420570 如何以倾斜效果\u003Cem\u003E显示\u003C\u002Fem\u003E文字 3430571 如何以阴影效果\u003Cem\u003E显示\u003C\u002Fem\u003E文字 3430572 如何以倒影效果\u003Cem\u003E显示\u003C\u002Fem\u003E文字 3440573 如何以投影效果\u003Cem\u003E显示\u003C\u002Fem\u003E文字 3440574 如何以浮雕效果\u003Cem\u003E显示\u003C\u002Fem\u003E文字 3450575 如何以印版效果\u003Cem\u003E显示\u003C\u002Fem\u003E文字 3460576 如何为文字填充图片纹理 3460577 如何创建可旋转文字 34713.5 图像识别及图像工具 3470578 如何获取图像的像素值 3470579 如何设置图像的像素值 3480580 如何校正图像\u003Cem\u003E显示\u003C\u002Fem\u003E颜色 3490581 如何使用阈值校正图像\u003Cem\u003E显示\u003C\u002Fem\u003E颜色 3510582 如何获得图像信息 3520583 如何制作简单的画图工具 3530584 如何将图片以Image类型存储到\u003Cem\u003E数据\u003C\u002Fem\u003E库 3560585 如何从\u003Cem\u003E数据\u003C\u002Fem\u003E库\u003Cem\u003E中\u003C\u002Fem\u003E读取Image类型的字段 35713.6 图像应用及其他 3580586 如何在\u003Cem\u003EWeb\u003C\u002Fem\u003E页面上\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3580587 绘制渐变背景图像 3590588 确定鼠标是否在图形范围内 3590589 如何绘制柱形图 3600590 如何绘制饼形图 3620591 如何绘制折线图 3640592 如何绘制图形验证码 3660593 如何在桌面上全屏\u003Cem\u003E显示\u003C\u002Fem\u003E图像 3670594 如何利用Image制作小动画 3680595 如何使用鼠标拖动图片 3680596 如何获取当前鼠标的形状 369第14章 动画与多媒体 37114.1 声音控制 3720597 如何播放WAV声音文件 3720598 如何播放默认的Beep事件声音 3720599 如何播放默认的Hand事件声音 3720600 如何播放默认的Asterisk事件声音 3720601 如何播放默认的Question事件声音 3730602 如何播放默认的Exclamation事件声音 3730603 如何设置计算机喇叭发出的声音 3730604 如何同步加载并播放声音文件 3740605 如何异步加载并播放声音文件 37414.2 多媒体及其他 3750606 C#实现动画效果 3750607 C#设计屏幕保护程序 3750608 如何实现滚动字幕 3760609 如何播放AVI动画文件 3760610 如何播放Flash 3770611 用C#实现家庭影集 3780612 C#实现电影特效 3790613 如何实现Word艺术字 3790614 检查是否安装声卡 3800615 带有记忆功能的MP3 3800616 打开和关闭光驱 3810617 如何收听网络电台 3820618 如何通过剪贴板复制粘贴图像 3820619 如何转换图像文件的保存格式 3830620 如何制作自动播放的MP3播放器 3840621 学校体操定时音乐播放 3850622 如何从ARGB分量值创建Color结构 3850623 如何动画\u003Cem\u003E显示\u003C\u002Fem\u003E窗体 3860624 如何获取系统的图像编码器信息 3870625 如何获取系统的图像解码器信息 388第15章 键盘与鼠标 38915.1 鼠标操作技巧 3900626 鼠标双击窗体时模拟键盘Tab键操作 3900627 定义鼠标指针形状 3900628 自定义鼠标的图片 3910629 鼠标拖放复制文本 3910630 如何使用鼠标单击添加控件 3920631 如何获得鼠标在窗体上的位置 3920632 如何交换鼠标左右键功能 3920633 如何隐藏和\u003Cem\u003E显示\u003C\u002Fem\u003E鼠标 3930634 如何获取光标闪烁的频率 3940635 如何获得屏幕上鼠标的坐标 3940636 如何限制鼠标在某一区域工作 3940637 如何利用鼠标绘图 3950638 如何获取鼠标双击时间间隔 3960639 如何获取鼠标键数 3960640 如何\u003Cem\u003E显示\u003C\u002Fem\u003E鼠标的等待光标 3970641 如何禁用鼠标左键 3970642 如何模拟鼠标操作 3980643 如何实现鼠标穿透窗体 3990644 如何记录鼠标行为 39915.2 键盘操作技巧应用 4000645 如何禁用输入法编辑器 4000646 如何打开和关闭输入法编辑器 4000647 回车转换成Tab键 4000648 如何获取组合键 4010649 如何获取功能键 4010650 如何判断NumLock键和CapsLock键是否锁定 4010651 如何屏蔽+键关闭窗体 4020652 如何实现按下键关闭窗体 4020653 如何避免按键产生“嘀”声 4030654 如何设置键盘热键 403第16章 文件、文件管理及\u003Cem\u003E数据\u003C\u002Fem\u003E流 40516.1 获取文件基本信息 4060655 获取文件创建的日期和时间 4060656 如何检索路径\u003Cem\u003E中\u003C\u002Fem\u003E的文件名和扩展名 4060657 如何获得文件的大小 4070658 如何修改文件属性 4070659 如何监视文件系统变化情况 4080660 如何获取文件的系统启动方式 4080661 如何获取文件名禁止使用的字符 4090662 如何获取路径名禁止使用的字符 4100663 如何获取指定目录的上级目录 41016.2 文件基本操作 4110664 判断文件是否存在 4110665 创建一个文件用于写入UTF-8编码的文本 4110666 OpenRead方法打开现有文件并读取 4120667 打开现有UTF-8编码文本文件并进行读取 4120668 OpenWrite方法打开现有文件并进行写入 4130669 如何读取文件\u003Cem\u003E中\u003C\u002Fem\u003E的第一行\u003Cem\u003E数据\u003C\u002Fem\u003E 4130670 如何向文件\u003Cem\u003E中\u003C\u002Fem\u003E写入\u003Cem\u003E数据\u003C\u002Fem\u003E 4130671 如何读取文件\u003Cem\u003E中\u003C\u002Fem\u003E所有\u003Cem\u003E数据\u003C\u002Fem\u003E 4140672 如何创建临时文件 4140673 如何实现文件替换 4150674 使用递归法删除文件夹\u003Cem\u003E中\u003C\u002Fem\u003E所有文件 4150675 如何更改文件扩展名 4160676 如何实现复制文件 4160677 如何修改文件名 4160678 如何删除文件 4170679 如何上传文件 4170680 如何下载文件 4180681 如何拖放文件 4190682 如何搜索文件 41916.3 文件夹基本操作 4200683 如何创建文件夹 4200684 如何移动文件夹 4200685 如何修改文件夹名称 4210686 如何遍历文件夹 4210687 如何删除文件夹 42216.4 \u003Cem\u003E数据\u003C\u002Fem\u003E流操作 4220688 如何读写内存\u003Cem\u003E数据\u003C\u002Fem\u003E流 4220689 如何创建二进制文件 4230690 如何读取二进制文件 4230691 如何使用缓冲流 42416.5 加密、解密及解压缩文件 4250692 加密和解密文件 4250693 如何使用对称算法加密文件 4250694 如何使用对称算法解密文件 4260695 如何使用GZip压缩文件 4270696 如何使用GZip解压文件 4280697 如何使用WinRAR压缩文件 4290698 如何使用WinRAR解压文件 42916.6 其他 4300699 设置文件的访问模式 4300700 如何在C#应用程序\u003Cem\u003E中\u003C\u002Fem\u003E使用INI文件 4300701 如何操作帮助文件 4310702 如何操作Word文件 4320703 如何操作Excel文件 4330704 如何将文本文件转换成网页文件 4340705 如何产生随机文件夹名或文件名 4350706 如何将长文件名转换成短文件名 4360707 如何用程序创建XML文档并写入内容 4360708 如何通过DataSet对象读取XML文件 4380709 如何动态创建XML文件节点 4390710 如何实现XML文件\u003Cem\u003E数据\u003C\u002Fem\u003E类型的转换 4390711 将图片保存到XML文件\u003Cem\u003E中\u003C\u002Fem\u003E 4400712 如何比较两个文件的内容是否相同 4400713 如何以缩略图形式上传图片文件 4410714 如何解析只有一种格式的文本文件 4420715 如何解析含有多种格式的文本文件 443第17章 Windows开发技术 44517.1 获取计算机系统信息 4460716 如何获取系统时间 4460717 如何获取系统目录 4460718 如何获取计算机名称 4460719 如何获取当前程序运行目录 4460720 如何获得操作系统版本号 44617.2 获取计算机硬件信息 4460721 如何获取CPU编号 4460722 如何获取\u003Cem\u003E显示\u003C\u002Fem\u003E设备的PNPDeviceID 4470723 如何获取声音设备的PNPDeviceID 4470724 如何获取硬盘编号 4470725 如何获取CPU的版本信息 4480726 如何获取CPU的产品名称信息 4480727 如何获取CPU的制造商名称 4480728 如何获取主板制造商 4490729 如何获取主板编号 4490730 如何获取主板型号 4490731 如何获取磁盘空间 4500732 如何获取磁盘剩余空间 4500733 如何确定屏幕的分辨率 4510734 如何获得磁盘的卷标 4520735 如何获得磁盘的文件系统类型 45217.3 获取特殊文件夹路径 4530736 如何获取ProgramFiles目录全路径 4530737 如何获取桌面目录全路径 4530738 如何获取开始菜单目录全路径 4540739 如何获取用户程序组目录全路径 4540740 如何获取文档模板目录全路径 4550741 如何获取收藏夹目录全路径 4550742 如何获取共享组件目录全路径 4560743 如何获取我的图片目录全路径 4560744 如何获取Internet历史记录全路径 4570745 如何获取Internet临时文件目录全路径 4570746 如何设置可用样式 45717.4 获得Windows当前用户 4580747 如何获取当前用户 4580748 如何判断当前用户是否是普通用户 4580749 如何判断当前用户是否是超级用户 4580750 如何判断当前用户是否是系统管理员 4590751 如何判断当前用户是否是系统操作员 4590752 如何判断当前用户是否是备份操作员 4600753 如何判断当前用户是否是打印操作员 4600754 如何判断当前用户是否是复制程序员 4610755 如何判断当前用户是否是账户操作员 46117.5 Windows日志 4620756 如何获取系统日志信息 4620757 如何获取安全日志信息 4620758 如何获取应用程序日志信息 4630759 如何创建并写入自定义日志信息 4640760 如何向系统日志写入自定义\u003Cem\u003E数据\u003C\u002Fem\u003E 4640761 如何向应用程序日志写入自定义信息 46517.6 计算机控制 4650762 列举系统\u003Cem\u003E中\u003C\u002Fem\u003E所有窗口 4650763 C#实现键盘钩子 4650764 如何关闭计算机 4660765 如何抓屏 4660766 如何休眠计算机 4670767 如何禁止使用Windows任务管理器 4680768 如何为文件新增右键菜单项 4680769 如何设置系统仅能运行的程序 4690770 如何获取本地计算机上所有的进程 4690771 如何启动一个进程 4700772 怎样杀死一个进程 4700773 如何获取远程计算机上所有的进程 47017.7 其他相关技术 4700774 如何在注册表\u003Cem\u003E中\u003C\u002Fem\u003E保存窗体的大小和位置 4700775 如何实现程序间注册表内传递变量 4710776 在使用OpenFileDialog\u003Cem\u003E中\u003C\u002Fem\u003E的相对路径问题 4710777 如何设置启动时自动执行程序 4710778 C#编程实现Windows XP风格的界面 4710779 用C#实现文件查找功能 4730780 如何序列化对象 4730781 如何实现特殊形状的窗体 4740782 如何移动正在使用的文件 4740783 如何实现类似QQ的程序界面 4750784 如何实现动画\u003Cem\u003E显示\u003C\u002Fem\u003E窗体 4760785 如何\u003Cem\u003E显示\u003C\u002Fem\u003E和隐藏任务栏 4770786 如何实现OutLook界面 4780787 如何在C#\u003Cem\u003E中\u003C\u002Fem\u003E回车换行 4780788 如何获取进程的命令行 4790789 如何按行读取文本并\u003Cem\u003E显示\u003C\u002Fem\u003E行数 4790790 如何在Form\u003Cem\u003E中\u003C\u002Fem\u003E嵌入Excel 4790791 如何使用互斥量禁止程序运行两个实例 4800792 如何使用进程名禁止程序运行两个实例 4800793 如何获取控制台应用程序的\u003Cem\u003E显示\u003C\u002Fem\u003E结果 4810794 如何用@代替路径\u003Cem\u003E中\u003C\u002Fem\u003E的转义字符 482第18章 程序应用控制 48318.1 提取信息 4840795 判断驱动器类型并获取其属性 4840796 如何得到本地机器的IP 4840797 如何得到本地运行的EXE的路径 4850798 得到计算机所有正在运行的进程 4850799 获得Windows的启动模式 4850800 获取鼠标的按钮个数及鼠标安装状态 4850801 检测计算机是否存在网络连接 4860802 如何判断计算机的联机状态 4860803 获取计算机屏幕分辨率 4860804 获取计算机当前登录的用户名称 48618.2 系统控制 4860805 远程关闭或重新启动计算机 4860806 创建应用程序快捷方式 4870807 启动Windows系统服务 4880808 在C#应用程序\u003Cem\u003E中\u003C\u002Fem\u003E控制输入法 4880809 打开“区域和语言选项”对话框并指定选项卡 4890810 如何执行命令行命令? 4890811 如何修改计算机的默认打印机 4900812 如何实现行业软件系统注销功能 4900813 如何将计算机设置为休眠状态 4900814 在Windows系统\u003Cem\u003E中\u003C\u002Fem\u003E建立事件日志 4910815 如何使PC喇叭发音 49118.3 程序控制 4910816 使用回车键控制鼠标焦点 4910817 如何调用可执行应用程序 4920818 TextBox上禁用鼠标右鍵 4920819 如何实现屏幕截图 4920820 如何将截取的图片保存为指定图片格式 4930821 如何复制程序本身 4930822 分段\u003Cem\u003E显示\u003C\u002Fem\u003E电话号码颜色 4930823 软件版本号是如何组成的 4930824 单击“关闭”按钮或按+键时最小化窗口 4940825 屏蔽RichTextBox控件+快捷键 49518.4 其他 4950826 将DataGridView控件\u003Cem\u003E中\u003C\u002Fem\u003E的\u003Cem\u003E数据\u003C\u002Fem\u003E导入Excel 4950827 无法获取自定义环境变量的值 4960828 将组件放到COM+服务器上去 4960829 调用非托管的DLL文件 4970830 如何将GridView控件\u003Cem\u003E数据\u003C\u002Fem\u003E导入Word 4970831 如何将GridView控件\u003Cem\u003E数据\u003C\u002Fem\u003E导入Excel 4970832 单片机如何实现在线调试 4980833 单片机如何实现内存优化管理 4980834 单片机实现文件系统管理 4980835 杀死进程 4980836 如何下载某网站上的图片资源 498第19章 SQL查询相关技术 50119.1 常用SQL查询技术 5020837 如何在查询\u003Cem\u003E中\u003C\u002Fem\u003E正确使用单引号“’” 5020838 SQL\u003Cem\u003E中\u003C\u002Fem\u003ESELECT语句的执行顺序 5020839 在查询时查询\u003Cem\u003E数据\u003C\u002Fem\u003E为指定长度的\u003Cem\u003E数据\u003C\u002Fem\u003E 5020840 如何利用WHERE参数过滤\u003Cem\u003E数据\u003C\u002Fem\u003E 5030841 如何正确地理解和运用SQL\u003Cem\u003E中\u003C\u002Fem\u003E的判式 5030842 如何正确地理解和使用SQL\u003Cem\u003E中\u003C\u002Fem\u003E的关键字 50319.2 比较、逻辑运算符查询 5040843 如何使用算术运算符号进行比较查询 5040844 如何使用比较运算符号进行比较查询 5040845 如何使用AND逻辑运算符查询 5050846 如何使用OR逻辑运算符查询 5060847 如何联合使用AND和OR运算符查询 5060848 如何在查询\u003Cem\u003E中\u003C\u002Fem\u003E正确使用逻辑操作符 5070849 利用通配符进行查询 50719.3 SQL关键字查询 5080850 如何使用ESCAPE关键字规定转义字符 5080851 如何使用BETWEEN进行范围查询 5080852 如何使用NOT BETWEEN进行范围查询 5090853 如何使用GROUP BY子句查询 5090854 如何使用HAVING语句过滤分组\u003Cem\u003E数据\u003C\u002Fem\u003E 5100855 如何使用ALL关键字查询 5100856 如何使用CUBE关键字查询 51119.4 表结构与性能 5110857 检测信息是否存在 5110858 @@CPU_BUSY获取CPU的工作时间 5110859 如何获取磁盘读写次数 5120860 获取SQL Server服务器名 5120861 获取\u003Cem\u003E数据\u003C\u002Fem\u003E库标识号 5120862 判断用户是否访问\u003Cem\u003E数据\u003C\u002Fem\u003E的权限 5120863 \u003Cem\u003E显示\u003C\u002Fem\u003E表\u003Cem\u003E中\u003C\u002Fem\u003E列信息 5120864 \u003Cem\u003E显示\u003C\u002Fem\u003E表\u003Cem\u003E中\u003C\u002Fem\u003E任意列名称 5130865 提高SQL性能加快执行速度 5130866 控制批处理内语句的执行 5130867 执行查询但是\u003Cem\u003E显示\u003C\u002Fem\u003E列信息 5140868 获取连接或试图连接的次数 5140869 获取当前\u003Cem\u003E数据\u003C\u002Fem\u003E库的语言名 51419.5 时间与谓词 5140870 时间函数的使用 5140871 设置\u003Cem\u003E数据\u003C\u002Fem\u003E库时间表显形式 5150872 格式化日期\u003Cem\u003E显示\u003C\u002Fem\u003E格式 5150873 如何正确理解SQL\u003Cem\u003E中\u003C\u002Fem\u003E的NULL值 5160874 如何使用IsNull()函数来处理空值 5160875 如何使用Nullif()函数来处理空值 5160876 查询空值(NULL)的技巧 5170877 利用关键字DISTINCT去除重复记录 5170878 巧用TOP子句获取信息 5180879 巧用CONTAINS谓词检索信息 5180880 通过ISNULL替换信息 5190881 比较COMPUTE和GROUP BY 5190882 如何对指定时间段进行查询 5190883 对某期间的\u003Cem\u003E数据\u003C\u002Fem\u003E进行查询的几种方法 5190884 NOT与谓词进行组合条件的查询 52019.6 聚合函数 5200885 聚合函数SUM的使用 5200886 聚合函数AVG的使用 5210887 如何使用聚合函数MAX 5210888 如何使用聚合函数MIN 5220889 如何使用聚合函数COUNT 5220890 如何使用聚合函数First或Last 52319.7 子查询与连接查询 5230891 union与连接之间的区别 5230892 如何应用IN查询表\u003Cem\u003E中\u003C\u002Fem\u003E的记录信息 5240893 使用一个单行的子查询来更新列 5240894 使用IN引入子查询限定查询范围 5240895 在UPDATE语句\u003Cem\u003E中\u003C\u002Fem\u003E应用子查询 5250896 如何应用子查询 5250897 EXISTS与子查询联合应用 5250898 在FROM子句\u003Cem\u003E中\u003C\u002Fem\u003E的子查询 5250899 在DELETE语句\u003Cem\u003E中\u003C\u002Fem\u003E应用子查询 5260900 子查询与聚合函数的应用 5260901 有效使用内连接 5260902 如何使用LEFT OUTER JOIN查询 5260903 如何使用RIGHT OUTER JOIN查询 5270904 利用CASE语句查询结果 52719.8 交叉表 5280905 Access\u003Cem\u003E中\u003C\u002Fem\u003E利用TRASFORM分析\u003Cem\u003E数据\u003C\u002Fem\u003E 5280906 Access\u003Cem\u003E中\u003C\u002Fem\u003E利用TRASFORM动态分析\u003Cem\u003E数据\u003C\u002Fem\u003E 5290907 SQL Server实现静态交叉表 5290908 SQL Server实现动态交叉表 53119.9 常用\u003Cem\u003E数据\u003C\u002Fem\u003E操作 5320909 如何对字符串进行查询 5320910 如何进行单条\u003Cem\u003E数据\u003C\u002Fem\u003E的添加 5330911 如何进行批量\u003Cem\u003E数据\u003C\u002Fem\u003E的添加 5330912 如何对\u003Cem\u003E数据\u003C\u002Fem\u003E进行修改 5340913 如何对\u003Cem\u003E数据\u003C\u002Fem\u003E进行删除 5340914 对\u003Cem\u003E数据\u003C\u002Fem\u003E库\u003Cem\u003E数据\u003C\u002Fem\u003E进行局部删除 53419.10 高级应用 5350915 如何使用临时表 5350916 如何查询表\u003Cem\u003E中\u003C\u002Fem\u003E的列名 5350917 在查询\u003Cem\u003E中\u003C\u002Fem\u003E如何防止输入指定符串 5360918 查询指定长度的\u003Cem\u003E数据\u003C\u002Fem\u003E 5360919 获取当前\u003Cem\u003E数据\u003C\u002Fem\u003E库的详细信息 5370920 在查询过程\u003Cem\u003E中\u003C\u002Fem\u003E灵活定义与使用别名 53819.11 视图、存储过程和触发器的使用 5380921 如何正确认识视图 5380922 如何获取\u003Cem\u003E数据\u003C\u002Fem\u003E库\u003Cem\u003E中\u003C\u002Fem\u003E的全部用户视图 5390923 如何通过视图修改\u003Cem\u003E数据\u003C\u002Fem\u003E 5390924 如何正确理解存储过程 5400925 如何获取\u003Cem\u003E数据\u003C\u002Fem\u003E库\u003Cem\u003E中\u003C\u002Fem\u003E的全部存储过程 5400926 如何正确认识触发器 5410927 Update触发器在系统日志\u003Cem\u003E中\u003C\u002Fem\u003E的应用 5420928 触发器的嵌套使用 5420929 获取\u003Cem\u003E数据\u003C\u002Fem\u003E库\u003Cem\u003E中\u003C\u002Fem\u003E的触发器 54319.12 其他 5440930 在查询程序\u003Cem\u003E中\u003C\u002Fem\u003E使用变量 5440931 对查询结果进行排序 5440932 批量获取结果集信息 5450933 对查询结果生成表 5450934 实现\u003Cem\u003E数据\u003C\u002Fem\u003E类型转换 5460935 获取当前\u003Cem\u003E数据\u003C\u002Fem\u003E库的登录用户名 5460936 如何正确理解\u003Cem\u003E数据\u003C\u002Fem\u003E库键字 5460937 将结果转换为XML形式 5470938 追加查询结果到已存在的表 5470939 利用对多个表\u003Cem\u003E中\u003C\u002Fem\u003E的字段创建新记录集 5470940 利用EXECUTE执行SQL语句 548第20章 \u003Cem\u003E数据\u003C\u002Fem\u003E库技术 54920.1 Access\u003Cem\u003E数据\u003C\u002Fem\u003E库的使用 5500941 如何为Access\u003Cem\u003E数据\u003C\u002Fem\u003E库设置密码 5500942 如何创建加密的Access\u003Cem\u003E数据\u003C\u002Fem\u003E库 5500943 建立Access\u003Cem\u003E数据\u003C\u002Fem\u003E库连接 5510944 与加密后的Access\u003Cem\u003E数据\u003C\u002Fem\u003E库建立连接 5510945 如何提取Access\u003Cem\u003E数据\u003C\u002Fem\u003E库\u003Cem\u003E中\u003C\u002Fem\u003E的\u003Cem\u003E数据\u003C\u002Fem\u003E表名 5510946 随机读取Access\u003Cem\u003E数据\u003C\u002Fem\u003E库记录 5520947 将Access\u003Cem\u003E数据\u003C\u002Fem\u003E库导入到Excel\u003Cem\u003E中\u003C\u002Fem\u003E(ASP.NET) 5520948 在.NET 2.0框架下动态创建Access\u003Cem\u003E数据\u003C\u002Fem\u003E库 5530949 在.NET 2.0框架下动态创建Access\u003Cem\u003E数据\u003C\u002Fem\u003E表 5530950 如何备份Access\u003Cem\u003E数据\u003C\u002Fem\u003E库 55420.2 SQL\u003Cem\u003E数据\u003C\u002Fem\u003E库的使用 5540951 建立SQL Server\u003Cem\u003E数据\u003C\u002Fem\u003E库连接 5540952 如何使用ODBC访问SQL Server\u003Cem\u003E数据\u003C\u002Fem\u003E库 5550953 读取SQL Server\u003Cem\u003E数据\u003C\u002Fem\u003E表结构 5560954 在C#\u003Cem\u003E中\u003C\u002Fem\u003E分离SQL Server\u003Cem\u003E数据\u003C\u002Fem\u003E库 5570955 C#\u003Cem\u003E中\u003C\u002Fem\u003E附加SQL Server\u003Cem\u003E数据\u003C\u002Fem\u003E库 5580956 C#\u003Cem\u003E中\u003C\u002Fem\u003E附加单文件SQL Server\u003Cem\u003E数据\u003C\u002Fem\u003E库 5590957 备份SQL Server\u003Cem\u003E数据\u003C\u002Fem\u003E库 5590958 还原SQL Server\u003Cem\u003E数据\u003C\u002Fem\u003E库 5600959 开启SQL Server\u003Cem\u003E数据\u003C\u002Fem\u003E库服务 5610960 断开SQL Server\u003Cem\u003E数据\u003C\u002Fem\u003E库服务 5620961 如何判断SQL Server\u003Cem\u003E数据\u003C\u002Fem\u003E库连接状态 5620962 获取连接SQL Server\u003Cem\u003E数据\u003C\u002Fem\u003E库的名称 5630963 获取SQL Server的连接统计\u003Cem\u003E数据\u003C\u002Fem\u003E 5630964 如何调用SQL Server存储过程 5630965 如何生成SQL\u003Cem\u003E数据\u003C\u002Fem\u003E库脚本 5640966 SQL Server 2000无法安装的解决办法 56520.3 其他 5650967 如何判断记录是否为NULL 5650968 建立Oracle\u003Cem\u003E数据\u003C\u002Fem\u003E库连接 5660969 如何在\u003Cem\u003E数据\u003C\u002Fem\u003E表\u003Cem\u003E中\u003C\u002Fem\u003E设置主键 5660970 DataSet读取XML文件\u003Cem\u003E中\u003C\u002Fem\u003E\u003Cem\u003E数据\u003C\u002Fem\u003E作为\u003Cem\u003E数据\u003C\u002Fem\u003E源 5670971 如何读取Fox的DBF文件 5670972 通用方法实现\u003Cem\u003E数据\u003C\u002Fem\u003E增、删、改功能 5670973 通用方法获取查询结果DataSet\u003Cem\u003E数据\u003C\u002Fem\u003E集 5680974 同时查询多条SQL语句 5680975 如何判断是否查询到结果 5680976 将图片以二进制格式存储到\u003Cem\u003E数据\u003C\u002Fem\u003E库\u003Cem\u003E中\u003C\u002Fem\u003E(asp.net) 5690977 从DataReader对象读取\u003Cem\u003E数据\u003C\u002Fem\u003E的技巧 5690978 随机\u003Cem\u003E显示\u003C\u002Fem\u003E\u003Cem\u003E数据\u003C\u002Fem\u003E库记录 5690979 通过DataTable获得\u003Cem\u003E数据\u003C\u002Fem\u003E表的主键 5690980 将Access\u003Cem\u003E数据\u003C\u002Fem\u003E库转化为SQL Server\u003Cem\u003E数据\u003C\u002Fem\u003E库 5700981 将SQL Server\u003Cem\u003E数据\u003C\u002Fem\u003E库转化为Access\u003Cem\u003E数据\u003C\u002Fem\u003E库 5710982 如何避免\u003Cem\u003E数据\u003C\u002Fem\u003E库死锁现象 5720983 如何调用带输入参数的存储过程 5720984 如何获取存储过程返回的结果集 5730985 取得\u003Cem\u003E数据\u003C\u002Fem\u003E表某个单元格的值 5730986 在ASP.NET2.0下将\u003Cem\u003E数据\u003C\u002Fem\u003E绑定DropDownList 5730987 在ADO.NET\u003Cem\u003E中\u003C\u002Fem\u003E实现\u003Cem\u003E数据\u003C\u002Fem\u003E库的事务处理 5740988 将任意文件保存到\u003Cem\u003E数据\u003C\u002Fem\u003E库\u003Cem\u003E中\u003C\u002Fem\u003E 5740989 将存储在\u003Cem\u003E数据\u003C\u002Fem\u003E库\u003Cem\u003E中\u003C\u002Fem\u003E的文件提取出来 5750990 合并具有相同\u003Cem\u003E数据\u003C\u002Fem\u003E表结构的查询结果 5750991 使用DataTable进行\u003Cem\u003E数据\u003C\u002Fem\u003E检索 5750992 使用DataView对\u003Cem\u003E数据\u003C\u002Fem\u003E进行检索和排序 5760993 使用DataSet建立DataTable明细表 576第21章 打印与报表技术 57921.1 报表设计技术 5800994 如何快速创建水晶报表 5800995 如何编写带图片的报表 5820996 如何使图片成为整个报表的背景 5830997 如何设置水晶报表\u003Cem\u003E中\u003C\u002Fem\u003E节的背景图片 5830998 如何设置水晶报表\u003Cem\u003E中\u003C\u002Fem\u003E节的背景色 5840999 如何设置水晶报表的页面 5841000 如何在报表\u003Cem\u003E中\u003C\u002Fem\u003E添加节 5841001 如何在报表\u003Cem\u003E中\u003C\u002Fem\u003E移动节的顺序 5851002 如何在报表\u003Cem\u003E中\u003C\u002Fem\u003E合并节 5851003 如何在报表\u003Cem\u003E中\u003C\u002Fem\u003E册除节 5851004 如何在报表\u003Cem\u003E中\u003C\u002Fem\u003E\u003Cem\u003E显示\u003C\u002Fem\u003E与隐藏节 5861005 如何设置多列样式报表 5861006 如何设置报表\u003Cem\u003E中\u003C\u002Fem\u003E节的高度 5871007 如何设置报表的摘要信息 5871008 如何设置报表的打印日期与时间 58721.2 报表格式化类对象技巧 5881009 如何在报表\u003Cem\u003E中\u003C\u002Fem\u003E使用文本对象 5881010 如何移动对象操作 5881011 如何对齐多个对象 5891012 如何使用公式字段 5891013 如何在报表\u003Cem\u003E中\u003C\u002Fem\u003E使用线 5901014 如何在报表\u003Cem\u003E中\u003C\u002Fem\u003E使用方框 59021.3 报表\u003Cem\u003E数据\u003C\u002Fem\u003E排序与分组技巧 5911015 如何排序报表\u003Cem\u003E数据\u003C\u002Fem\u003E 5911016 如何报表\u003Cem\u003E数据\u003C\u002Fem\u003E分组 5911017 如何报表\u003Cem\u003E中\u003C\u002Fem\u003E筛选\u003Cem\u003E数据\u003C\u002Fem\u003E 5921018 如何对分组报表\u003Cem\u003E中\u003C\u002Fem\u003E的页码进行设置 59221.4 报表的应用技巧 5931019 如何在水晶报表\u003Cem\u003E中\u003C\u002Fem\u003E使用交叉表 5931020 如何在水晶报表\u003Cem\u003E中\u003C\u002Fem\u003E使用子报表 5941021 如何动态\u003Cem\u003E显示\u003C\u002Fem\u003E子报表 5961022 如何删除子报表 5971023 如何在报表\u003Cem\u003E中\u003C\u002Fem\u003E计算百分比 59721.5 Windows打印控件应用技巧 5991024 如何使用PrintDocument控件打印窗体\u003Cem\u003E数据\u003C\u002Fem\u003E 5991025 如何使用PrintPreviewContronl控件预览 5991026 使用PrintPreviewDialog对话框 6001027 如何使用PrintDialog对话框打印 6011028 如何使用PageSetupDialog对话框设置页面 6011029 如何使用PrintDocument控件打印文本文件 602第22章 C#高级应用开发 60522.1 线程的使用 6061030 如何开始一个线程 6061031 如何结束一个线程 6061032 如何使线程休眠 6061033 如何挂起一个线程 6061034 如何判断线程的状态 6061035 如何实现线程的同步 6071036 如何避免死锁 60722.2 .NET 2.0的新特性 6071037 如何使用泛型 6071038 如何使用匿名方法 6081039 如何使用迭代器 6091040 如何使用分部类 61022.3 C#\u003Cem\u003EWeb\u003C\u002Fem\u003EService 6101041 建立SQL Server返回\u003Cem\u003E数据\u003C\u002Fem\u003E集\u003Cem\u003EWeb\u003C\u002Fem\u003EService 6101042 利用\u003Cem\u003EWeb\u003C\u002Fem\u003EService传送图片 61122.4 文件监视 6111043 如何监视文件的创建 6111044 如何监视文件的改变 6121045 如何监视文件的重命名 6121046 如何监视文件的删除 61322.5 C#高级应用 6131047 如何将聊天程序做成Windows服务 6131048 COM+服务解决同时访问大量\u003Cem\u003E数据\u003C\u002Fem\u003E并发性 6151049 COM+服务实现银行转账系统 6171050 如何用Remoting技术传送文件 6191051 大规模\u003Cem\u003E数据\u003C\u002Fem\u003E访问时缓解服务器压力 620第23章 硬件及相关开发技术 62323.1 语音卡、IC卡、神龙卡的使用 6241052 利用语音卡拨","createTime":"2008-06-01 08:59:33","dataReportQuery":"spm=1035.2023.3001.6557&utm_medium=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-3-477425-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default&depth_1-utm_source=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-3-477425-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default","dataReportClick":"{\"mod\":\"popu_645\",\"index\":\"3\",\"dest\":\"https:\u002F\u002Fdownload.csdn.net\u002Fdownload\u002Fsis_ying\u002F477425\",\"strategy\":\"2~default~OPENSEARCH~Rate\",\"extra\":\"{\\\"utm_medium\\\":\\\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-3-477425-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\\\",\\\"dist_request_id\\\":\\\"1713920331325_95453\\\"}\",\"spm\":\"1035.2023.3001.6557\"}","dataReportView":"{\"mod\":\"popu_645\",\"index\":\"3\",\"dest\":\"https:\u002F\u002Fdownload.csdn.net\u002Fdownload\u002Fsis_ying\u002F477425\",\"strategy\":\"2~default~OPENSEARCH~Rate\",\"extra\":\"{\\\"utm_medium\\\":\\\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-3-477425-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\\\",\\\"dist_request_id\\\":\\\"1713920331325_95453\\\"}\",\"spm\":\"1035.2023.3001.6557\"}","type":"download"},{"url":"https:\u002F\u002Fdownload.csdn.net\u002Fdownload\u002Fyxbbbs283127372\u002F3325262","title":"二十三种设计模式【PDF版】","desc":"主要是介绍各种格式流行的软件设计模式,对于程序员的进一步提升起推进作用,有时间可以随便翻翻~~\n23种设计模式汇集 \n如果你还不了解设计模式是什么的话? \n那就先看设计模式引言 ! \n\n学习 GoF 设计模式的重要性 \n建筑和软件\u003Cem\u003E中\u003C\u002Fem\u003E模式之异同 \n\nA. 创建模式 \n设计模式之 Singleton(单态\u002F单件) 阎宏博士讲解:单例(Singleton)模式 \n保证一个类只有一个实例,并提供一个访问它的全局访问点 \n设计模式之 Factory(工厂方法和抽象工厂) \n使用工厂模式就象使用 new 一样频繁. \n设计模式之 Builder \n汽车由车轮 方向盘 发动机很多部件组成,同时,将这些部件组装成汽车也是一件复杂的工作,Builder 模式就是将这两\n种情况分开进行。 \n设计模式之 Prototype(原型) \n用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 \n\nB. 结构模式 \n设计模式之 Adapter(适配器) \n使用类再生的两个方式:组合(new)和继承(extends),这个已经在 thinking in java\u003Cem\u003E中\u003C\u002Fem\u003E提到过. \n设计模式之 Proxy(代理) \n以 Jive 为例,剖析代理模式在用户级别授权机制上的应用 \n设计模式之 Facade(门面?) \n可扩展的使用 JDBC针对不同的\u003Cem\u003E数据\u003C\u002Fem\u003E库编程,Facade提供了一种灵活的实现. \n设计模式之 Composite(组合) \n就是将类用\u003Cem\u003E树形\u003C\u002Fem\u003E结构组合成一个单位.你向别人介绍你是某单位,你是单位\u003Cem\u003E中\u003C\u002Fem\u003E的一个元素,别人和你做买卖,相当于\n和单位做买卖。文章\u003Cem\u003E中\u003C\u002Fem\u003E还对 Jive再进行了剖析。 \n设计模式之 Decorator(装饰器) \nDecorator 是个油漆工,给你的东东的外表刷上美丽的颜色. \n设计模式之 Bridge(桥连) \n将牛郎织女分开(本应在一起,分开他们,形成两个接口),在他们之间搭建一个桥(动态的结合) \n设计模式之 Flyweight(共享元) \n提供 Java运行性能,降低小而大量重复的类的开销. \n\nC. 行为模式 \n设计模式之 Command(命令) \n什么是将行为封装,Command 是最好的说明. \n设计模式之 Observer(观察者) \n介绍如何使用 Java API 提供的现成 Observer \n设计模式之 Iterator(迭代器) \n这个模式已经被整合入Java的Collection.在大多数场合下无需自己制造一个Iterator,只要将对象装入Collection\u003Cem\u003E中\u003C\u002Fem\u003E,\n直接使用 Iterator 进行对象遍历。 \n设计模式之 Template(模板方法) 实际上向你介绍了为什么要使用 Java 抽象类,该模式原理简单,使用很普遍. \n设计模式之 Strategy(策略) \n不同算法各自封装,用户端可随意挑选需要的算法. \n设计模式之 Chain of Responsibility(责任链) \n各司其职的类串成一串,好象击鼓传花,当然如果自己能完成,就不要推委给下一个. \n设计模式之 Mediator(\u003Cem\u003E中\u003C\u002Fem\u003E介) \nMediator 很象十字路口的红绿灯,每个车辆只需和红绿灯交互就可以. \n设计模式之 State(状态) \n状态是编程\u003Cem\u003E中\u003C\u002Fem\u003E经常碰到的实例,将状态对象化,设立状态变换器,便可在状态\u003Cem\u003E中\u003C\u002Fem\u003E轻松切换. \n设计模式之 Memento(注释状态?) \n很简单一个模式,就是在内存\u003Cem\u003E中\u003C\u002Fem\u003E保留原来\u003Cem\u003E数据\u003C\u002Fem\u003E的拷贝. \n设计模式之 Interpreter(解释器) \n主要用来对语言的分析,应用机会不多. \n设计模式之 Visitor(访问者) \n访问者在进行访问时,完成一系列实质性操作,而且还可以扩展. \n\n设计模式引言 \n设计面向对象软件比较困难,而设计可复用的面向对象软件就更加困难。你必须找到相关的对象,以适当的粒度将它们归\n类,再定义类的接口和继承层次,建立对象之间的基本关系。你的设计应该对手头的问题有针对性,同时对将来的问题和需求\n也要有足够的通用性。 \n你也希望避免重复设计或尽可能少做重复设计。有经验的面向对象设计者会告诉你,要一下子就得到复用性和灵活性好的设计,\n即使不是不可能的至少也是非常困难的。一个设计在最终完成之前常要被复用好几次,而且每一次都有所修改。 \n有经验的面向对象设计者的确能做出良好的设计,而新手则面对众多选择无从下手,总是求助于以前使用过的非面向对象\n技术。新手需要花费较长时间领会良好的面向对象设计是怎么回事。有经验的设计者显然知道一些新手所不知道的东西,这又\n是什么呢? \n内行的设计者知道:不是解决任何问题都要从头做起。他们更愿意复用以前使用过的解决方案。当找到一个好的解决方案,他\n们会一遍又一遍地使用。这些经验是他们成为内行的部分原因。因此,你会在许多面向对象系统\u003Cem\u003E中\u003C\u002Fem\u003E看到类和相互通信的对象( c \no m m u n i c a t i n go b j e c t)的重复模式。这些模式解决特定的设计问题,使面向对象设计更灵活、优雅,最终复用性更\n好。它们帮助设计者将新的设计建立在以往工作的基础上,复用以往成功的设计方案。 \n一个熟悉这些模式的设计者不需要再去发现它们,而能够立即将它们应用于设计问题\u003Cem\u003E中\u003C\u002Fem\u003E。以下类比可以帮助说明这一点。\n小说家和剧本作家很少从头开始设计剧情。他们总是沿袭一些业已存在的模式,像“悲剧性英雄”模式(《麦克白》、《哈姆雷特》\n等)或“浪漫小说”模式(存在着无数浪漫小说)。同样地,面向对象设计员也沿袭一些模式,像“用对象表示状态”和“修饰对象以便\n于你能容易地添加\u002F删除属性”等。一旦懂得了模式,许多设计决策自然而然就产生了。 \n我们都知道设计经验的重要价值。你曾经多少次有过这种感觉—你已经解决过了一个问题但就是不能确切知道是在什么地\n方或怎么解决的?如果你能记起以前问题的细节和怎么解决它的,你就可以复用以前的经验而不需要重新发现它。然而,我们\n并没有很好记录下可供他人使用的软件设计经验。 \n学习 GoF设计模式的重要性 \n著名的 EJB 领域顶尖的专家 Richard Monson-Haefel 在其个人网站:www.EJBNow.com \u003Cem\u003E中\u003C\u002Fem\u003E极力推荐的 GoF 的《设计模式》,原文\n如下: \nDesign Patterns \nMost developers claim to experience an epiphany reading this book. If you've never read the Design Patterns book then you have \nsuffered a very serious gap in your programming education that should be remedied immediately. \n翻译: 很多程序员在读完这本书,宣布自己相当于经历了一次\"主显节\"(纪念那稣降生和受洗的双重节日),如果你从来没有读\n过这本书,你会在你的程序教育生涯里存在一个严重裂沟,所以你应该立即挽救弥补! 可以这么说:GoF 设计模式是程序员真正掌握面向对象核心思想的必修课。虽然你可能已经通过了 SUN 的很多令人炫目的\n技术认证,但是如果你没有学习掌握 GoF 设计模式,只能说明你还是一个技工。 \n在浏览《Thingking in Java》(第一版)时,你是不是觉得好象这还是一本 Java 基础语言书籍?但又不纯粹是,因为这本书的作\n者将面向对象的思想巧妙的融合在 Java 的具体技术上,潜移默化的让你感觉到了一种新的语言和新的思想方式的诞生。 \n但是读完这本书,你对书\u003Cem\u003E中\u003C\u002Fem\u003E这些蕴含的思想也许需要一种更明晰更系统更透彻的了解和掌握,那么你就需要研读 GoF 的《设\n计模式》了。 \n《Thingking in Java》(第一版\u003Cem\u003E中\u003C\u002Fem\u003E文)是这样描述设计模式的:他在由 Gamma, Helm 和 Johnson Vlissides 简称 Gang of Four(四人\n帮),缩写 GoF 编著的《Design Patterns》一书\u003Cem\u003E中\u003C\u002Fem\u003E被定义成一个“里程碑”。事实上,那本书现在已成为几乎所有 OOP(面向对象程\n序设计)程序员都必备的参考书。(在国外是如此)。 \nGoF 的《设计模式》是所有面向对象语言(C++ Java C#)的基础,只不过不同的语言将之实现得更方便地使用。 \nGOF 的设计模式是一座\"桥\" \n就 Java 语言体系来说,GOF 的设计模式是 Java 基础知识和 J2EE 框架知识之间一座隐性的\"桥\"。 \n会 Java 的人越来越多,但是一直徘徊在语言层次的程序员不在少数,真正掌握 Java \u003Cem\u003E中\u003C\u002Fem\u003E接口或抽象类的应用不是很多,大家\n经常以那些技术只适合大型项目为由,避开或忽略它们,实际\u003Cem\u003E中\u003C\u002Fem\u003E,Java 的接口或抽象类是真正体现 Java 思想的核心所在,这些\n你都将在 GoF 的设计模式里领略到它们变幻无穷的魔力。 \nGoF 的设计模式表面上好象也是一种具体的\"技术\",而且新的设计模式不断在出现,设计模式自有其自己的发展轨道,而这\n些好象和 J2EE .Net 等技术也无关! \n实际上,GoF 的设计模式并不是一种具体\"技术\",它讲述的是思想,它不仅仅展示了接口或抽象类在实际案例\u003Cem\u003E中\u003C\u002Fem\u003E的灵活应用\n和智慧,让你能够真正掌握接口或抽象类的应用,从而在原来的 Java 语言基础上跃进一步,更重要的是,GoF 的设计模式反复\n向你强调一个宗旨:要让你的程序尽可能的可重用。 \n这其实在向一个极限挑战:软件需求变幻无穷,计划没有变化快,但是我们还是要寻找出不变的东西,并将它和变化的东\n西分离开来,这需要非常的智慧和经验。 \n而 GoF 的设计模式是在这方面开始探索的一块里程碑。 \nJ2EE 等属于一种框架软件,什么是框架软件?它不同于我们以前接触的 Java API 等,那些属于 Toolkist(工具箱),它不再被动\n的被使用,被调用,而是深刻的介入到一个领域\u003Cem\u003E中\u003C\u002Fem\u003E去,J2EE 等框架软件设计的目的是将一个领域\u003Cem\u003E中\u003C\u002Fem\u003E不变的东西先定义好,比如\n整体结构和一些主要职责(如\u003Cem\u003E数据\u003C\u002Fem\u003E库操作 事务跟踪 安全等),剩余的就是变化的东西,针对这个领域\u003Cem\u003E中\u003C\u002Fem\u003E具体应用产生的具体不同\n的变化需求,而这些变化东西就是 J2EE 程序员所要做的。 \n由此可见,设计模式和 J2EE 在思想和动机上是一脉相承,只不过 \n1.设计模式更抽象,J2EE 是具体的产品代码,我们可以接触到,而设计模式在对每个应用时才会产生具体代码。 \n2.设计模式是比 J2EE 等框架软件更小的体系结构,J2EE \u003Cem\u003E中\u003C\u002Fem\u003E许多具体程序都是应用设计模式来完成的,当你深入到 J2EE 的内\n部代码研究时,这点尤其明显,因此,如果你不具备设计模式的基础知识(GoF 的设计模式),你很难快速的理解 J2EE。不能理解\nJ2EE,如何能灵活应用? \n3.J2EE 只是适合企业计算应用的框架软件,但是 GoF 的设计模式几乎可以用于任何应用!因此 GoF 的设计模式应该是 J2EE\n的重要理论基础之一。 \n所以说,GoF 的设计模式是 Java 基础知识和 J2EE 框架知识之间一座隐性的\"桥\"。为什么说隐性的? \nGOF 的设计模式是一座隐性的\"桥\" \n因为很多人没有注意到这点,学完 Java 基础语言就直接去学 J2EE,有的甚至鸭子赶架,直接使用起 \u003Cem\u003EWeb\u003C\u002Fem\u003Elogic 等具体 J2EE 软\n件,一段时间下来,发现不过如此,挺简单好用,但是你真正理解 J2EE 了吗?你在具体案例\u003Cem\u003E中\u003C\u002Fem\u003E的应用是否也是在延伸 J2EE 的思\n想? \n如果你不能很好的延伸 J2EE 的思想,那你岂非是大炮轰蚊子,认识到 J2EE 不是适合所有场合的人至少是明智的,但我们更\n需要将 J2EE 用对地方,那么只有理解 J2EE 此类框架软件的精髓,那么你才能真正灵活应用 Java 解决你的问题,甚至构架出你自\n己企业的框架来。(我们不能总是使用别人设定好的框架,为什么不能有我们自己的框架?) \n因此,首先你必须掌握 GoF 的设计模式。虽然它是隐性,但不是可以越过的。 \n关于本站“设计模式” Java 提供了丰富的 API,同时又有强大的\u003Cem\u003E数据\u003C\u002Fem\u003E库系统作底层支持,那么我们的编程似乎变成了类似积木的简单\"拼凑\"和调用,\n甚至有人提倡\"蓝领程序员\",这些都是对现代编程技术的不了解所至. \n在真正可复用的面向对象编程\u003Cem\u003E中\u003C\u002Fem\u003E,GoF 的《设计模式》为我们提供了一套可复用的面向对象技术,再配合 Refactoring(重构方法),\n所以很少存在简单重复的工作,加上Java 代码的精炼性和面向对象纯洁性(设计模式是 java 的灵魂),编程工作将变成一个让你时刻\n体验创造快感的激动人心的过程. \n为能和大家能共同探讨\"设计模式\",我将自己在学习\u003Cem\u003E中\u003C\u002Fem\u003E的心得写下来,只是想帮助更多人更容易理解 GoF 的《设计模式》。由\n于原著都是以C++为例, 以Java为例的设计模式基本又都以图形应用为例,而我们更关心Java在\u003Cem\u003E中\u003C\u002Fem\u003E间件等服务器方面的应用,因此,\n本站所有实例都是非图形应用,并且顺带剖析 Jive论坛系统.同时为降低理解难度,尽量避免使用 UML 图. \n如果你有一定的面向对象编程经验,你会发现其\u003Cem\u003E中\u003C\u002Fem\u003E某些设计模式你已经无意识的使用过了;如果你是一个新手,那么从开始就\n培养自己良好的编程习惯(让你的的程序使用通用的模式,便于他人理解;让你自己减少重复性的编程工作),这无疑是成为一个优秀\n程序员的必备条件. \n整个设计模式贯穿一个原理:面对接口编程,而不是面对实现.目标原则是:降低耦合,增强灵活性. \n建筑和软件\u003Cem\u003E中\u003C\u002Fem\u003E模式之异同 \nCSDN 的透明特别推崇《建筑的永恒之道》,认为从\u003Cem\u003E中\u003C\u002Fem\u003E探寻到软件的永恒之道,并就\"设计模式\"写了专门文章《探寻软件的永恒\n之道 》,其\u003Cem\u003E中\u003C\u002Fem\u003E很多观点我看了很受启发,以前我也将\"设计模式\" 看成一个简单的解决方案,没有从一种高度来看待\"设计模式\"在软\n件\u003Cem\u003E中\u003C\u002Fem\u003E地位,下面是我自己的一些想法: \n建筑和软件某些地方是可以来比喻的 \n特别是\u003Cem\u003E中\u003C\u002Fem\u003E国传统建筑,那是很讲模式的,这些都是传统文化使然,比如京剧 一招一式都有套路;\u003Cem\u003E中\u003C\u002Fem\u003E国画,也有套路,树应该怎么画\n法?有几种画法?艺术大家通常是创造出自己的套路,比如明末清初,水墨画法开始成熟,这时画树就不用勾勒这个模式了,而是一笔\n下去,浓淡几个叶子,待毛笔的水墨要干枯时,画一下树干,这样,一个活生写意的树就画出来. \n我上面这些描述其实都是一种模式,创建模式的人是大师,但是拘泥于模式的人永远是工匠. \n再回到传统建筑\u003Cem\u003E中\u003C\u002Fem\u003E,\u003Cem\u003E中\u003C\u002Fem\u003E国的传统建筑是过分注重模式了,所以建筑风格发展不大,基本分南北两派,大家有个感觉,旅游时,到南\n方,你发现古代名居建筑都差不多;北方由于受满人等少数民族的影响,在建筑色彩上有些与南方迥异,但是很多细节地方都差不多.\n这些都是模式的体现. \n由于建筑受材料和功用以及费用的影响,所用模式种类不多,这点是和软件很大的不同. \n正因为这点不同,导致建筑的管理模式和软件的管理模式就有很多不同, 有些人认识不到这点,就产生了可以大量使用\"软件\n蓝领\"的想法,因为他羡慕建筑\u003Cem\u003E中\u003C\u002Fem\u003E\"民工\"的低成本. \n要知道软件还有一个与建筑截然相反的责任和用途,那就是:现代社会\u003Cem\u003E中\u003C\u002Fem\u003E,计划感不上变化,竞争激烈,所有一切变幻莫测,要应\n付所有这些变化,首推信息技术\u003Cem\u003E中\u003C\u002Fem\u003E的软件,只有软件能够帮助人类去应付各种变化.而这点正好与建筑想反,建筑是不能帮助人类去\n应付变化的,(它自己反而要求稳固,老老实实帮助人遮风避雨,总不能叫人类在露天或树叶下打开电脑编软件吧). \n软件要帮助人类去应付变化,这是软件的首要责任,所以,软件\u003Cem\u003E中\u003C\u002Fem\u003E模式产生的目的就和建筑不一样了,建筑\u003Cem\u003E中\u003C\u002Fem\u003E的模式产生可以因\n为很多原因:建筑大师的创意;材料的革新等;建筑\u003Cem\u003E中\u003C\u002Fem\u003E这些模式一旦产生,容易发生另外一个缺点,就是有时会阻碍建筑本身的发展,\n因为很多人会不思创造,反复使用老的模式进行设计,阻碍建筑的发展. \n但是在软件\u003Cem\u003E中\u003C\u002Fem\u003E,这点正好相反,软件模式的产生是因为变化的东西太多,为减轻人类的负担,将一些不变的东西先用模式固化,这\n样让人类可以更加集\u003Cem\u003E中\u003C\u002Fem\u003E精力对付变化的东西,所以在软件\u003Cem\u003E中\u003C\u002Fem\u003E大量反复使用模式(我个人认为这样的软件就叫框架软件了,比如J2EE),\n不但没阻碍软件的发展,反而是推动了软件的发展.因为其他使用这套软件的人就可以将更多精力集\u003Cem\u003E中\u003C\u002Fem\u003E在对付那些无法用模式的\n应用上来. \n可以关于建筑和软件\u003Cem\u003E中\u003C\u002Fem\u003E的模式作用可以总结如下: \n在软件\u003Cem\u003E中\u003C\u002Fem\u003E,模式是帮助人类向\"变化\"战斗,但是在软件\u003Cem\u003E中\u003C\u002Fem\u003E还需要和'变化'直接面对面战斗的武器:人的思维,特别是创造 分析思\n维等等,这些是软件真正的灵魂,这种思维可以说只要有实践需求(如有新项目)就要求发生,发生频度高,人类的创造或分析思\n维决定了软件的质量和特点。 \n而在建筑\u003Cem\u003E中\u003C\u002Fem\u003E,模式可以构成建筑全部知识,当有新的需求(如有新项目),一般使用旧的模式都可以完成,因此对人类的创造以\n及分析思维不是每个项目都必须的,也不是非常重要的,对创造性的思维的需求只是属于锦上添花(除非人类以后离开地球居\n住了〕。 设计模式之 Singleton(单态) \n模式实战书籍《Java实用系统开发指南》 \n单态定义: \nSingleton 模式主要作用是保证在 Java 应用程序\u003Cem\u003E中\u003C\u002Fem\u003E,一个类 Class 只有一个实例存在。 \n在很多操作\u003Cem\u003E中\u003C\u002Fem\u003E,比如建立目录 \u003Cem\u003E数据\u003C\u002Fem\u003E库连接都需要这样的单线程操作。 \n还有, singleton 能够被状态化; 这样,多个单态类在一起就可以作为一个状态仓库一样向外提供服务,比如,你要论坛\u003Cem\u003E中\u003C\u002Fem\u003E的\n帖子计数器,每次浏览一次需要计数,单态类能否保持住这个计数,并且能 synchronize 的安全自动加 1,如果你要把这个数字\n永久保存到\u003Cem\u003E数据\u003C\u002Fem\u003E库,你可以在不修改单态接口的情况下方便的做到。 \n另外方面,Singleton 也能够被无状态化。提供工具性质的功能, \nSingleton 模式就为我们提供了这样实现的可能。使用 Singleton 的好处还在于可以节省内存,因为它限制了实例的个数,有\n利于 Java 垃圾回收(garbage collection)。 \n我们常常看到工厂模式\u003Cem\u003E中\u003C\u002Fem\u003E类装入器(class loader)\u003Cem\u003E中\u003C\u002Fem\u003E也用 Singleton 模式实现的,因为被装入的类实际也属于资源。 \n如何使用? \n一般 Singleton 模式通常有几种形式: \npublic class Singleton { \nprivate Singleton(){} \n\u002F\u002F在自己内部定义自己一个实例,是不是很奇怪? \n\u002F\u002F注意这是 private 只供内部调用 \nprivate static Singleton instance = new Singleton(); \n\u002F\u002F这里提供了一个供外部访问本 class 的静态方法,可以直接访问 \npublic static Singleton getInstance() { \nreturn instance; \n} \n} \n第二种形式: \npublic class Singleton { \nprivate static Singleton instance = null; \npublic static synchronized Singleton getInstance() { \n\u002F\u002F这个方法比上面有所改进,不用每次都进行生成对象,只是第一次 \n\u002F\u002F使用时生成实例,提高了效率! \nif (instance==null) \ninstance=new Singleton(); \nreturn instance; } \n} \n使用 Singleton.getInstance()可以访问单态类。 \n上面第二\u003Cem\u003E中\u003C\u002Fem\u003E形式是 lazy initialization,也就是说第一次调用时初始 Singleton,以后就不用再生成了。 \n注意到 lazy initialization 形式\u003Cem\u003E中\u003C\u002Fem\u003E的 synchronized,这个 synchronized 很重要,如果没有 synchronized,那么使用 getInstance()\n是有可能得到多个 Singleton 实例。关于 lazy initialization 的 Singleton 有很多涉及 double-checked locking (DCL)的讨论,有兴趣者\n进一步研究。 \n一般认为第一种形式要更加安全些。 \n使用 Singleton 注意事项: \n有时在某些情况下,使用 Singleton 并不能达到 Singleton 的目的,如有多个 Singleton 对象同时被不同的类装入器装载;在\nEJB 这样的分布式系统\u003Cem\u003E中\u003C\u002Fem\u003E使用也要注意这种情况,因为 EJB 是跨服务器,跨 JVM 的。 \n我们以 SUN 公司的宠物店源码(Pet Store 1.3.1)的 ServiceLocator 为例稍微分析一下: 在 Pet Store\u003Cem\u003E中\u003C\u002Fem\u003E ServiceLocator 有两种,一个是 EJB 目录下;一个是 \u003Cem\u003EWEB\u003C\u002Fem\u003E 目录下,我们检查这两个 ServiceLocator 会发现内容\n差不多,都是提供 EJB 的查询定位服务,可是为什么要分开呢?仔细研究对这两种 ServiceLocator 才发现区别:在 \u003Cem\u003EWEB\u003C\u002Fem\u003E \u003Cem\u003E中\u003C\u002Fem\u003E的\nServiceLocator 的采取 Singleton 模式,ServiceLocator 属于资源定位,理所当然应该使用 Singleton 模式。但是在 EJB \u003Cem\u003E中\u003C\u002Fem\u003E,Singleton\n模式已经失去作用,所以 ServiceLocator 才分成两种,一种面向 \u003Cem\u003EWEB\u003C\u002Fem\u003E 服务的,一种是面向 EJB 服务的。 \nSingleton 模式看起来简单,使用方法也很方便,但是真正用好,是非常不容易,需要对 Java 的类 线程 内存等概念有相当\n的了解。 \n总之:如果你的应用基于容器,那么 Singleton 模式少用或者不用,可以使用相关替代技术。 \n进一步深入可参考: \nDouble-checked locking and the Singleton pattern \nWhen is a singleton not a singleton? \n设计模式如何在具体项目\u003Cem\u003E中\u003C\u002Fem\u003E应用见《Java 实用系统开发指南》。 \n设计模式之 Factory \n工厂模式定义:提供创建对象的接口. \n为何使用? \n工厂模式是我们最常用的模式了,著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。 \n为什么工厂模式是如此常用?因为工厂模式就相当于创建实例对象的 new,我们经常要根据类 Class 生成实例对象,如 A \na=new A() 工厂模式也是用来创建实例对象的,所以以后 new时就要多个心眼,是否可以考虑实用工厂模式,虽然这样做,\n可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。 \n我们以类 Sample为例, 如果我们要创建 Sample的实例对象: \nSample sample=new Sample(); \n可是,实际情况是,通常我们都要在创建 sample实例时做点初始化的工作,比如赋值 查询\u003Cem\u003E数据\u003C\u002Fem\u003E库等。 \n首先,我们想到的是,可以使用 Sample的构造函数,这样生成实例就写成: \nSample sample=new Sample(参数); \n但是,如果创建 sample 实例时所做的初始化工作不是象赋值这样简单的事,可能是很长一段代码,如果也写入构造函数\n\u003Cem\u003E中\u003C\u002Fem\u003E,那你的代码很难看了(就需要 Refactor 重整)。 \n为什么说代码很难看,初学者可能没有这种感觉,我们分析如下,初始化工作如果是很长一段代码,说明要做的工作很多,\n将很多工作装入一个方法\u003Cem\u003E中\u003C\u002Fem\u003E,相当于将很多鸡蛋放在一个篮子里,是很危险的,这也是有背于 Java 面向对象的原则,面向对象\n的封装(Encapsulation)和分派(Delegation)告诉我们,尽量将长的代码分派“切割”成每段,将每段再“封装”起来(减少段和段\n之间偶合联系性),这样,就会将风险分散,以后如果需要修改,只要更改每段,不会再发生牵一动百的事情。 \n在本例\u003Cem\u003E中\u003C\u002Fem\u003E,首先,我们需要将创建实例的工作与使用实例的工作分开, 也就是说,让创建实例所需要的大量初始化工作从\nSample的构造函数\u003Cem\u003E中\u003C\u002Fem\u003E分离出去。 \n这时我们就需要 Factory 工厂模式来生成对象了,不能再用上面简单 new Sample(参数)。还有,如果 Sample 有个继承\n如 MySample, 按照面向接口编程,我们需要将 Sample 抽象成一个接口.现在 Sample 是接口,有两个子类 MySample 和\nHisSample .我们要实例化他们时,如下: \nSample mysample=new MySample(); \nSample hissample=new HisSample(); \n随着项目的深入,Sample可能还会\"生出很多儿子出来\", 那么我们要对这些儿子一个个实例化,更糟糕的是,可能还要对以\n前的代码进行修改:加入后来生出儿子的实例.这在传统程序\u003Cem\u003E中\u003C\u002Fem\u003E是无法避免的. \n但如果你一开始就有意识使用了工厂模式,这些麻烦就没有了. \n工厂方法 \n你会建立一个专门生产 Sample实例的工厂: \npublic class Factory{ \npublic static Sample creator(int which){ \n\u002F\u002FgetClass 产生 Sample 一般可使用动态类装载装入类。 if (which==1) \nreturn new SampleA(); \nelse if (which==2) \nreturn new SampleB(); \n} \n} \n那么在你的程序\u003Cem\u003E中\u003C\u002Fem\u003E,如果要实例化 Sample 时.就使用 \nSample sampleA=Factory.creator(1); \n这样,在整个就不涉及到 Sample 的具体子类,达到封装效果,也就减少错误修改的机会,这个原理可以用很通俗的话来比喻:\n就是具体事情做得越多,越容易范错误.这每个做过具体工作的人都深有体会,相反,官做得越高,说出的话越抽象越笼统,范错误可\n能性就越少.好象我们从编程序\u003Cem\u003E中\u003C\u002Fem\u003E也能悟出人生道理?呵呵. \n使用工厂方法 要注意几个角色,首先你要定义产品接口,如上面的 Sample,产品接口下有 Sample接口的实现类,如\nSampleA,其次要有一个 factory 类,用来生成产品 Sample,如下图,最右边是生产的对象 Sample: \n\n进一步稍微复杂一点,就是在工厂类上进行拓展,工厂类也有继承它的实现类 concreteFactory 了。 \n抽象工厂 \n工厂模式\u003Cem\u003E中\u003C\u002Fem\u003E有: 工厂方法(Factory Method) 抽象工厂(Abstract Factory). \n这两个模式区别在于需要创建对象的复杂程度上。如果我们创建对象的方法变得复杂了,如上面工厂方法\u003Cem\u003E中\u003C\u002Fem\u003E是创建一个对象\nSample,如果我们还有新的产品接口 Sample2. \n这里假设:Sample有两个 concrete 类 SampleA 和 SamleB,而 Sample2 也有两个 concrete类 Sample2A 和\nSampleB2 \n那么,我们就将上例\u003Cem\u003E中\u003C\u002Fem\u003E Factory 变成抽象类,将共同部分封装在抽象类\u003Cem\u003E中\u003C\u002Fem\u003E,不同部分使用子类实现,下面就是将上例\u003Cem\u003E中\u003C\u002Fem\u003E的\nFactory 拓展成抽象工厂: \npublic abstract class Factory{ \npublic abstract Sample creator(); \npublic abstract Sample2 creator(String name); \n} \npublic class SimpleFactory extends Factory{ \npublic Sample creator(){ \n......... \nreturn new SampleA \n} \npublic Sample2 creator(String name){ \n......... \nreturn new Sample2A \n} } \npublic class BombFactory extends Factory{ \npublic Sample creator(){ \n...... \nreturn new SampleB \n} \npublic Sample2 creator(String name){ \n...... \nreturn new Sample2B \n} \n} \n从上面看到两个工厂各自生产出一套 Sample和 Sample2,也许你会疑问,为什么我不可以使用两个工厂方法来分别生产\nSample和 Sample2? \n抽象工厂还有另外一个关键要点,是因为 SimpleFactory 内,生产 Sample和生产 Sample2 的方法之间有一定联系,\n所以才要将这两个方法捆绑在一个类\u003Cem\u003E中\u003C\u002Fem\u003E,这个工厂类有其本身特征,也许制造过程是统一的,比如:制造工艺比较简单,所以\n名称叫 SimpleFactory。 \n在实际应用\u003Cem\u003E中\u003C\u002Fem\u003E,工厂方法用得比较多一些,而且是和动态类装入器组合在一起应用, \n举例 \n我们以 Jive的 ForumFactory 为例,这个例子在前面的 Singleton 模式\u003Cem\u003E中\u003C\u002Fem\u003E我们讨论过,现在再讨论其工厂模式: \npublic abstract class ForumFactory { \nprivate static Object initLock = new Object(); \nprivate static String className = \"com.jivesoftware.forum.database.DbForumFactory\"; \nprivate static ForumFactory factory = null; \npublic static ForumFactory getInstance(Authorization authorization) { \n\u002F\u002FIf no valid authorization passed in, return null. \nif (authorization == null) { \nreturn null; \n} \n\u002F\u002F以下使用了 Singleton 单态模式 \nif (factory == null) { \nsynchronized(initLock) { \nif (factory == null) { \n...... \ntry { \n\u002F\u002F动态转载类 \nClass c = Class.forName(className); \nfactory = (ForumFactory)c.newInstance(); \n} \ncatch (Exception e) { \nreturn null; \n} \n} \n} } \n\u002F\u002FNow, 返回 proxy.用来限制授权对 forum 的访问 \nreturn new ForumFactoryProxy(authorization, factory, \nfactory.getPermissions(authorization)); \n} \n\u002F\u002F真正创建 forum 的方法由继承 forumfactory 的子类去完成. \npublic abstract Forum createForum(String name, String description) \nthrows UnauthorizedException, ForumAlreadyExistsException; \n.... \n} \n因为现在的 Jive是通过\u003Cem\u003E数据\u003C\u002Fem\u003E库系统存放论坛帖子等内容\u003Cem\u003E数据\u003C\u002Fem\u003E,如果希望更改为通过文件系统实现,这个工厂方法\nForumFactory 就提供了提供动态接口: \nprivate static String className = \"com.jivesoftware.forum.database.DbForumFactory\"; \n你可以使用自己开发的创建 forum 的方法代替 com.jivesoftware.forum.database.DbForumFactory 就可以. \n在上面的一段代码\u003Cem\u003E中\u003C\u002Fem\u003E一共用了三种模式,除了工厂模式外,还有 Singleton 单态模式,以及 proxy模式,proxy 模式主要用来\n授权用户对 forum 的访问,因为访问 forum 有两种人:一个是注册用户 一个是游客 guest,那么那么相应的权限就不一样,而且\n这个权限是贯穿整个系统的,因此建立一个 proxy,类似网关的概念,可以很好的达到这个效果. \n看看 Java 宠物店\u003Cem\u003E中\u003C\u002Fem\u003E的 CatalogDAOFactory: \npublic class CatalogDAOFactory { \n\u002F** \n* 本方法制定一个特别的子类来实现 DAO 模式。 \n* 具体子类定义是在 J2EE 的部署描述器\u003Cem\u003E中\u003C\u002Fem\u003E。 \n*\u002F \npublic static CatalogDAO getDAO() throws CatalogDAOSysException { \nCatalogDAO catDao = null; \ntry { \nInitialContext ic = new InitialContext(); \n\u002F\u002F动态装入 CATALOG_DAO_CLASS \n\u002F\u002F可以定义自己的 CATALOG_DAO_CLASS,从而在无需变更太多代码 \n\u002F\u002F的前提下,完成系统的巨大变更。 \nString className =(String) ic.lookup(JNDINames.CATALOG_DAO_CLASS); \ncatDao = (CatalogDAO) Class.forName(className).newInstance(); \n} catch (NamingException ne) { \nthrow new CatalogDAOSysException(\" \nCatalogDAOFactory.getDAO: NamingException while \ngetting DAO type : \\n\" + ne.getMessage()); \n} catch (Exception se) { \nthrow new CatalogDAOSysException(\" \nCatalogDAOFactory.getDAO: Exception while getting \nDAO type : \\n\" + se.getMessage()); \n} \nreturn catDao; \n} \n} CatalogDAOFactory 是典型的工厂方法, catDao 是通过动态类装入器 className 获得 CatalogDAOFactory 具体实现\n子类,这个实现子类在 Java 宠物店是用来操作 catalog \u003Cem\u003E数据\u003C\u002Fem\u003E库,用户可以根据\u003Cem\u003E数据\u003C\u002Fem\u003E库的类型不同,定制自己的具体实现子类,\n将自己的子类名给与 CATALOG_DAO_CLASS 变量就可以。 \n由此可见,工厂方法确实为系统结构提供了非常灵活强大的动态扩展机制,只要我们更换一下具体的工厂方法,系统其他\n地方无需一点变换,就有可能将系统功能进行改头换面的变化。 \n设计模式之 Builder \nBuilder 模式定义: \n将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. \nBuilder 模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构建它们.用户不知\n道内部的具体构建细节.Builder 模式是非常类似抽象工厂模式,细微的区别大概只有在反复使用\u003Cem\u003E中\u003C\u002Fem\u003E才能体会到. \n为何使用? \n是为了将构建复杂对象的过程和它的部件解耦.注意: 是解耦过程和部件. \n因为一个复杂的对象,不但有很多大量组成部分,如汽车,有很多部件:车轮 方向盘 发动机还有各种小零件等等,部件很多,但\n远不止这些,如何将这些部件装配成一辆汽车,这个装配过程也很复杂(需要很好的组装技术),Builder 模式就是为了将部件和组装\n过程分开. \n如何使用? \n首先假设一个复杂对象是由多个部件组成的,Builder 模式是把复杂对象的创建和部件的创建分别开来,分别用 Builder 类和\nDirector 类来表示. \n首先,需要一个接口,它定义如何创建复杂对象的各个部件: \npublic interface Builder { \n\u002F\u002F创建部件 A 比如创建汽车车轮 \nvoid buildPartA(); \n\u002F\u002F创建部件 B 比如创建汽车方向盘 \nvoid buildPartB(); \n\u002F\u002F创建部件 C 比如创建汽车发动机 \nvoid buildPartC(); \n\u002F\u002F返回最后组装成品结果 (返回最后装配好的汽车) \n\u002F\u002F成品的组装过程不在这里进行,而是转移到下面的 Director 类\u003Cem\u003E中\u003C\u002Fem\u003E进行. \n\u002F\u002F从而实现了解耦过程和部件 \nProduct getResult(); \n} \n用 Director 构建最后的复杂对象,而在上面 Builder 接口\u003Cem\u003E中\u003C\u002Fem\u003E封装的是如何创建一个个部件(复杂对象是由这些部件组成的),也就\n是说 Director 的内容是如何将部件最后组装成成品: \npublic class Director { \nprivate Builder builder; \npublic Director( Builder builder ) { \nthis.builder = builder; \n} \n\u002F\u002F 将部件 partA partB partC 最后组成复杂对象 \n\u002F\u002F这里是将车轮 方向盘和发动机组装成汽车的过程 \npublic void construct() { \nbuilder.buildPartA(); \nbuilder.buildPartB(); \nbuilder.buildPartC(); } \n\n} \nBuilder 的具体实现 ConcreteBuilder: \n通过具体完成接口 Builder 来构建或装配产品的部件; \n定义并明确它所要创建的是什么具体东西; \n提供一个可以重新获取产品的接口: \npublic class ConcreteBuilder implements Builder { \nPart partA, partB, partC; \npublic void buildPartA() { \n\u002F\u002F这里是具体如何构建 partA 的代码 \n}; \npublic void buildPartB() { \n\u002F\u002F这里是具体如何构建 partB 的代码 \n}; \npublic void buildPartC() { \n\u002F\u002F这里是具体如何构建 partB 的代码 \n}; \npublic Product getResult() { \n\u002F\u002F返回最后组装成品结果 \n}; \n} \n复杂对象:产品 Product: \npublic interface Product { } \n复杂对象的部件: \npublic interface Part { } \n我们看看如何调用 Builder 模式: \nConcreteBuilder builder = new ConcreteBuilder(); \nDirector director = new Director( builder ); \ndirector.construct(); \nProduct product = builder.getResult(); \nBuilder 模式的应用 \n在 Java 实际使用\u003Cem\u003E中\u003C\u002Fem\u003E,我们经常用到\"池\"(Pool)的概念,当资源提供者无法提供足够的资源,并且这些资源需要被很多用户反复共\n享时,就需要使用池. \n\"池\"实际是一段内存,当池\u003Cem\u003E中\u003C\u002Fem\u003E有一些复杂的资源的\"断肢\"(比如\u003Cem\u003E数据\u003C\u002Fem\u003E库的连接池,也许有时一个连接会\u003Cem\u003E中\u003C\u002Fem\u003E断),如果循环再利用这\n些\"断肢\",将提高内存使用效率,提高池的性能.修改 Builder 模式\u003Cem\u003E中\u003C\u002Fem\u003E Director 类使之能诊断\"断肢\"断在哪个部件上,再修复这个部件. \n设计模式之 Prototype(原型) \n原型模式定义: \n用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. \nPrototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个\n原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。 \n如何使用? \n因为 Java \u003Cem\u003E中\u003C\u002Fem\u003E的提供 clone()方法来实现对象的克隆,所以 Prototype模式实现一下子变得很简单. \n以勺子为例: public abstract class AbstractSpoon implements Cloneable \n{ \nString spoonName; \npublic void setSpoonName(String spoonName) {this.spoonName = spoonName;} \npublic String getSpoonName() {return this.spoonName;} \npublic Object clone() \n{ \nObject object = null; \ntry { \nobject = super.clone(); \n} catch (CloneNotSupportedException exception) { \nSystem.err.println(\"AbstractSpoon is not Cloneable\"); \n} \nreturn object; \n} \n} \n有个具体实现(ConcretePrototype): \npublic class SoupSpoon extends AbstractSpoon \n{ \npublic SoupSpoon() \n{ \nsetSpoonName(\"Soup Spoon\"); \n} \n} \n调用 Prototype 模式很简单: \nAbstractSpoon spoon = new SoupSpoon(); \nAbstractSpoon spoon2 = spoon.clone(); \n当然也可以结合工厂模式来创建 AbstractSpoon 实例。 \n在 Java \u003Cem\u003E中\u003C\u002Fem\u003E Prototype 模式变成 clone()方法的使用,由于 Java 的纯洁的面向对象特性,使得在 Java \u003Cem\u003E中\u003C\u002Fem\u003E使用设计模式变\n得很自然,两者已经几乎是浑然一体了。这反映在很多模式上,如 Interator 遍历模式。 \n设计模式之 Adapter(适配器) \n适配器模式定义: \n将两个不兼容的类纠合在一起使用,属于结构型模式,需要有 Adaptee(被适配者)和 Adaptor(适配器)两个身份. \n为何使用? \n我们经常碰到要将两个没有关系的类组合在一起使用,第一解决方案是:修改各自类的接口,但是如果我们没有源代码,或\n者,我们不愿意为了一个应用而修改各自的接口。 怎么办? \n使用 Adapter,在这两种接口之间创建一个混合接口(混血儿). \n如何使用? \n实现 Adapter 方式,其实\"think in Java\"的\"类再生\"一节\u003Cem\u003E中\u003C\u002Fem\u003E已经提到,有两种方式:组合(composition)和继承\n(inheritance). \n假设我们要打桩,有两种类:方形桩 圆形桩. \npublic class SquarePeg{ \npublic void insert(String str){ System.out.println(\"SquarePeg insert():\"+str); \n} \n} \npublic class RoundPeg{ \npublic void insertIntohole(String msg){ \nSystem.out.println(\"RoundPeg insertIntoHole():\"+msg); \n} \n} \n现在有一个应用,需要既打方形桩,又打圆形桩.那么我们需要将这两个没有关系的类综合应用.假设 RoundPeg 我们没有源\n代码,或源代码我们不想修改,那么我们使用 Adapter 来实现这个应用: \npublic class PegAdapter extends SquarePeg{ \nprivate RoundPeg roundPeg; \npublic PegAdapter(RoundPeg peg)(this.roundPeg=peg;) \npublic void insert(String str){ roundPeg.insertIntoHole(str);} \n} \n在上面代码\u003Cem\u003E中\u003C\u002Fem\u003E,RoundPeg 属于 Adaptee,是被适配者.PegAdapter 是 Adapter,将 Adaptee(被适配者 RoundPeg)和\nTarget(目标 SquarePeg)进行适配.实际上这是将组合方法(composition)和继承(inheritance)方法综合运用. \nPegAdapter 首先继承 SquarePeg,然后使用 new 的组合生成对象方式,生成 RoundPeg 的对象 roundPeg,再重载父\n类 insert()方法。从这里,你也了解使用 new生成对象和使用 extends 继承生成对象的不同,前者无需对原来的类修改,甚至无\n需要知道其内部结构和源代码. \n如果你有些 Java 使用的经验,已经发现,这种模式经常使用。 \n进一步使用 \n上面的 PegAdapter 是继承了 SquarePeg,如果我们需要两边继承,即继承 SquarePeg 又继承 RoundPeg,因为 Java \u003Cem\u003E中\u003C\u002Fem\u003E\n不允许多继承,但是我们可以实现(implements)两个接口(interface) \npublic interface IRoundPeg{ \npublic void insertIntoHole(String msg); \n} \npublic interface ISquarePeg{ \npublic void insert(String str); \n} \n下面是新的 RoundPeg 和 SquarePeg, 除了实现接口这一区别,和上面的没什么区别。 \npublic class SquarePeg implements ISquarePeg{ \npublic void insert(String str){ \nSystem.out.println(\"SquarePeg insert():\"+str); \n} \n} \npublic class RoundPeg implements IRoundPeg{ \npublic void insertIntohole(String msg){ \nSystem.out.println(\"RoundPeg insertIntoHole():\"+msg); \n} \n} \n下面是新的 PegAdapter,叫做 two-way adapter: \npublic class PegAdapter implements IRoundPeg,ISquarePeg{ \nprivate RoundPeg roundPeg; private SquarePeg squarePeg; \n\u002F\u002F 构造方法 \npublic PegAdapter(RoundPeg peg){this.roundPeg=peg;} \n\u002F\u002F 构造方法 \npublic PegAdapter(SquarePeg peg)(this.squarePeg=peg;) \npublic void insert(String str){ roundPeg.insertIntoHole(str);} \n} \n还有一种叫 Pluggable Adapters,可以动态的获取几个 adapters \u003Cem\u003E中\u003C\u002Fem\u003E一个。使用 Reflection 技术,可以动态的发现类\u003Cem\u003E中\u003C\u002Fem\u003E的\nPublic 方法。 \n设计模式之 Proxy(代理) \n理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用\u003Cem\u003E中\u003C\u002Fem\u003E,可以如鱼得水,享受游刃有余的乐趣. \n代理模式是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,Proxy 是代理的意思,我们\n也许有代理服务器等概念,代理概念可以解释为:在出发点到目的地之间有一道\u003Cem\u003E中\u003C\u002Fem\u003E间层,意为代理. \n设计模式\u003Cem\u003E中\u003C\u002Fem\u003E定义: 为其他对象提供一种代理以控制对这个对象的访问. \n为什么要使用 Proxy? \n1.授权机制 不同级别的用户对同一对象拥有不同的访问权利,如 Jive 论坛系统\u003Cem\u003E中\u003C\u002Fem\u003E,就使用 Proxy 进行授权机制控制,访问\n论坛有两种人:注册用户和游客(未注册用户),Jive \u003Cem\u003E中\u003C\u002Fem\u003E就通过类似 ForumProxy 这样的代理来控制这两种用户对论坛的访问权\n限. \n2.某个客户端不能直接操作到某个对象,但又必须和那个对象有所互动. \n举例两个具体情况: \n(1)如果那个对象是一个是很大的图片,需要花费很长时间才能\u003Cem\u003E显示\u003C\u002Fem\u003E出来,那么当这个图片包含在文档\u003Cem\u003E中\u003C\u002Fem\u003E时,使用编辑器或浏\n览器打开这个文档,打开文档必须很迅速,不能等待大图片处理完成,这时需要做个图片 Proxy 来代替真正的图片. \n(2)如果那个对象在 Internet 的某个远端服务器上,直接操作这个对象因为网络速度原因可能比较慢,那我们可以先用\nProxy来代替那个对象. \n总之原则是,对于开销很大的对象,只有在使用它时才创建,这个原则可以为我们节省很多宝贵的 Java 内存. 所以,有些人认\n为 Java 耗费资源内存,我以为这和程序编制思路也有一定的关系. \n如何使用 Proxy? \n以 Jive 论坛系统为例,访问论坛系统的用户有多种类型:注册普通用户 论坛管理者 系统管理者 游客,注册普通用户才能发\n言;论坛管理者可以管理他被授权的论坛;系统管理者可以管理所有事务等,这些权限划分和管理是使用 Proxy完成的. \nForum 是 Jive的核心接口,在 Forum \u003Cem\u003E中\u003C\u002Fem\u003E陈列了有关论坛操作的主要行为,如论坛名称 论坛描述的获取和修改,帖子发表删\n除编辑等. \n在 ForumPermissions \u003Cem\u003E中\u003C\u002Fem\u003E定义了各种级别权限的用户: \npublic class ForumPermissions implements Cacheable { \n\u002F** \n* Permission to read object. \n*\u002F \npublic static final int READ = 0; \n\u002F** \n* Permission to administer the entire sytem. \n*\u002F \npublic static final int SYSTEM_ADMIN = 1; \n\u002F** \n* Permission to administer a particular forum. \n*\u002F public static final int FORUM_ADMIN = 2; \n\u002F** \n* Permission to administer a particular user. \n*\u002F \npublic static final int USER_ADMIN = 3; \n\u002F** \n* Permission to administer a particular group. \n*\u002F \npublic static final int GROUP_ADMIN = 4; \n\u002F** \n* Permission to moderate threads. \n*\u002F \npublic static final int MODERATE_THREADS = 5; \n\u002F** \n* Permission to create a new thread. \n*\u002F \npublic static final int CREATE_THREAD = 6; \n\u002F** \n* Permission to create a new message. \n*\u002F \npublic static final int CREATE_MESSAGE = 7; \n\u002F** \n* Permission to moderate messages. \n*\u002F \npublic static final int MODERATE_MESSAGES = 8; \n..... \npublic boolean isSystemOrForumAdmin() { \nreturn (values[FORUM_ADMIN] || values[SYSTEM_ADMIN]); \n} \n..... \n} \n因此,Forum \u003Cem\u003E中\u003C\u002Fem\u003E各种操作权限是和 ForumPermissions 定义的用户级别有关系的,作为接口 Forum 的实现:ForumProxy\n正是将这种对应关系联系起来.比如,修改 Forum 的名称,只有论坛管理者或系统管理者可以修改,代码如下: \npublic class ForumProxy implements Forum { \nprivate ForumPermissions permissions; \nprivate Forum forum; \nthis.authorization = authorization; \npublic ForumProxy(Forum forum, Authorization authorization, \nForumPermissions permissions) \n{ \nthis.forum = forum; \nthis.authorization = authorization; \nthis.permissions = permissions; } \n..... \npublic void setName(String name) throws UnauthorizedException, \nForumAlreadyExistsException \n{ \n\u002F\u002F只有是系统或论坛管理者才可以修改名称 \nif (permissions.isSystemOrForumAdmin()) { \nforum.setName(name); \n} \nelse { \nthrow new UnauthorizedException(); \n} \n} \n... \n} \n而 DbForum 才是接口 Forum 的真正实现,以修改论坛名称为例: \npublic class DbForum implements Forum, Cacheable { \n... \npublic void setName(String name) throws ForumAlreadyExistsException { \n.... \nthis.name = name; \n\u002F\u002F这里真正将新名称保存到\u003Cem\u003E数据\u003C\u002Fem\u003E库\u003Cem\u003E中\u003C\u002Fem\u003E \nsaveToDb(); \n.... \n} \n... \n} \n凡是涉及到对论坛名称修改这一事件,其他程序都首先得和ForumProxy打交道,由ForumProxy决定是否有权限做某一样\n事情,ForumProxy 是个名副其实的\"网关\",\"安全代理系统\". \n在平时应用\u003Cem\u003E中\u003C\u002Fem\u003E,无可避免总要涉及到系统的授权或安全体系,不管你有无意识的使用 Proxy,实际你已经在使用 Proxy了. \n我们继续结合 Jive谈入深一点,下面要涉及到工厂模式了,如果你不了解工厂模式,请看我的另外一篇文章:设计模式之\nFactory \n我们已经知道,使用 Forum 需要通过 ForumProxy,Jive \u003Cem\u003E中\u003C\u002Fem\u003E创建一个 Forum 是使用 Factory 模式,有一个总的抽象类\nForumFactory,在这个抽象类\u003Cem\u003E中\u003C\u002Fem\u003E,调用 ForumFactory 是通过 getInstance()方法实现,这里使用了 Singleton(也是设计模式\n之一,由于介绍文章很多,我就不写了),getInstance()返回的是 ForumFactoryProxy. \n为什么不返回 ForumFactory,而返回 ForumFactory 的实现 ForumFactoryProxy? \n原因是明显的,需要通过代理确定是否有权限创建 forum. \n在 ForumFactoryProxy \u003Cem\u003E中\u003C\u002Fem\u003E我们看到代码如下: \npublic class ForumFactoryProxy extends ForumFactory { \nprotected ForumFactory factory; \nprotected Authorization authorization; \nprotected ForumPermissions permissions; \npublic ForumFactoryProxy(Authorization authorization, ForumFactory factory, ForumPermissions permissions) \n{ \nthis.factory = factory; \nthis.authorization = authorization; \nthis.permissions = permissions; \n} \npublic Forum createForum(String name, String description) \nthrows UnauthorizedException, ForumAlreadyExistsException \n{ \n\u002F\u002F只有系统管理者才可以创建 forum \nif (permissions.get(ForumPermissions.SYSTEM_ADMIN)) { \nForum newForum = factory.createForum(name, description); \nreturn new ForumProxy(newForum, authorization, permissions); \n} \nelse { \nthrow new UnauthorizedException(); \n} \n} \n方法 createForum 返回的也是 ForumProxy, Proxy 就象一道墙,其他程序只能和 Proxy交互操作. \n注意到这里有两个 Proxy:ForumProxy 和 ForumFactoryProxy. 代表两个不同的职责:使用 Forum 和创建 Forum; \n至于为什么将使用对象和创建对象分开,这也是为什么使用 Factory 模式的原因所在:是为了\"封装\" \"分派\";换句话说,尽可\n能功能单一化,方便维护修改. \nJive论坛系统\u003Cem\u003E中\u003C\u002Fem\u003E其他如帖子的创建和使用,都是按照 Forum 这个思路而来的. \n以上我们讨论了如何使用Proxy进行授权机制的访问,Proxy还可以对用户隐藏另外一种称为copy-on-write的优化方式.\n拷贝一个庞大而复杂的对象是一个开销很大的操作,如果拷贝过程\u003Cem\u003E中\u003C\u002Fem\u003E,没有对原来的对象有所修改,那么这样的拷贝开销就没有必\n要.用代理延迟这一拷贝过程. \n比如:我们有一个很大的 Collection,具体如 hashtable,有很多客户端会并发同时访问它.其\u003Cem\u003E中\u003C\u002Fem\u003E一个特别的客户端要进行连\n续的\u003Cem\u003E数据\u003C\u002Fem\u003E获取,此时要求其他客户端不能再向 hashtable \u003Cem\u003E中\u003C\u002Fem\u003E增加或删除 东东. \n最直接的解决方案是:使用 collection 的 lock,让这特别的客户端获得这个 lock,进行连续的\u003Cem\u003E数据\u003C\u002Fem\u003E获取,然后再释放 lock. \npublic void foFetches(Hashtable ht){ \nsynchronized(ht){ \n\u002F\u002F具体的连续\u003Cem\u003E数据\u003C\u002Fem\u003E获取动作.. \n} \n} \n但是这一办法可能锁住 Collection 会很长时间,这段时间,其他客户端就不能访问该 Collection 了. \n第二个解决方案是clone这个Collection,然后让连续的\u003Cem\u003E数据\u003C\u002Fem\u003E获取针对clone出来的那个Collection操作.这个方案前提是,\n这个 Collection 是可 clone的,而且必须有提供深度 clone的方法.Hashtable 就提供了对自己的 clone方法,但不是 Key和\nvalue对象的 clone,关于 Clone含义可以参考专门文章. \npublic void foFetches(Hashtable ht){ \nHashttable newht=(Hashtable)ht.clone(); \n} \n问题又来了,由于是针对clone出来的对象操作,如果原来的母体被其他客户端操作修改了, 那么对clone出来的对象操作就\n没有意义了. 最后解决方案:我们可以等其他客户端修改完成后再进行 clone,也就是说,这个特别的客户端先通过调用一个叫 clone的方\n法来进行一系列\u003Cem\u003E数据\u003C\u002Fem\u003E获取操作.但实际上没有真正的进行对象拷贝,直至有其他客户端修改了这个对象 Collection. \n使用 Proxy实现这个方案.这就是 copy-on-write操作. \nProxy应用范围很广,现在流行的分布计算方式 RMI 和 Corba 等都是 Proxy模式的应用. \n更多 Proxy应用,见 http:\u002F\u002Fwww.research.umbc.edu\u002F~tarr\u002Fcs491\u002Flectures\u002FProxy.pdf \nSun 公司的 Explore the Dynamic Proxy API Dynamic Proxy Classes \n设计模式之 Facade(外观 总管 Manager) \nFacade 模式的定义: 为子系统\u003Cem\u003E中\u003C\u002Fem\u003E的一组接口提供一个一致的界面. \nFacade一个典型应用就是\u003Cem\u003E数据\u003C\u002Fem\u003E库 JDBC 的应用,如下例对\u003Cem\u003E数据\u003C\u002Fem\u003E库的操作: \npublic class DBCompare { \nConnection conn = null; \nPreparedStatement prep = null; \nResultSet rset = null; \ntry { \nClass.forName( \"\u003Cdriver\u003E\" ).newInstance(); \nconn = DriverManager.getConnection( \"\u003Cdatabase\u003E\" ); \nString sql = \"SELECT * FROM \u003Ctable\u003E WHERE \u003Ccolumn name\u003E = ?\"; \nprep = conn.prepareStatement( sql ); \nprep.setString( 1, \"\u003Ccolumn value\u003E\" ); \nrset = prep.executeQuery(); \nif( rset.next() ) { \nSystem.out.println( rset.getString( \"\u003Ccolumn name\" ) ); \n} \n} catch( SException e ) { \ne.printStackTrace(); \n} finally { \nrset.close(); \nprep.close(); \nconn.close(); \n} \n} \n上例是 Jsp \u003Cem\u003E中\u003C\u002Fem\u003E最通常的对\u003Cem\u003E数据\u003C\u002Fem\u003E库操作办法. \n在应用\u003Cem\u003E中\u003C\u002Fem\u003E,经常需要对\u003Cem\u003E数据\u003C\u002Fem\u003E库操作,每次都写上述一段代码肯定比较麻烦,需要将其\u003Cem\u003E中\u003C\u002Fem\u003E不变的部分提炼出来,做成一个接口,这\n就引入了 facade 外观对象.如果以后我们更换 Class.forName \u003Cem\u003E中\u003C\u002Fem\u003E的\u003Cdriver\u003E也非常方便,比如从 Mysql \u003Cem\u003E数据\u003C\u002Fem\u003E库换到 Oracle\n\u003Cem\u003E数据\u003C\u002Fem\u003E库,只要更换 facade接口\u003Cem\u003E中\u003C\u002Fem\u003E的 driver 就可以. \n我们做成了一个 Facade 接口,使用该接口,上例\u003Cem\u003E中\u003C\u002Fem\u003E的程序就可以更改如下: \npublic class DBCompare { \nString sql = \"SELECT * FROM \u003Ctable\u003E WHERE \u003Ccolumn name\u003E = ?\"; \ntry { \nMysql msql=new mysql(sql); \nprep.setString( 1, \"\u003Ccolumn value\u003E\" ); \nrset = prep.executeQuery(); \nif( rset.next() ) { System.out.println( rset.getString( \"\u003Ccolumn name\" ) ); \n} \n} catch( SException e ) { \ne.printStackTrace(); \n} finally { \nmysql.close(); \nmysql=null; \n} \n} \n可见非常简单,所有程序对\u003Cem\u003E数据\u003C\u002Fem\u003E库访问都是使用改接口,降低系统的复杂性,增加了灵活性. \n如果我们要使用连接池,也只要针对 facade接口修改就可以. \n\n由上图可以看出, facade实际上是个理顺系统间关系,降低系统间耦合度的一个常用的办法,也许你已经不知不觉在使用,尽\n管不知道它就是 facade. \n设计模式之 Composite(组合) \nComposite 模式定义: \n将对象以\u003Cem\u003E树形\u003C\u002Fem\u003E结构组织起来,以达成“部分-整体” 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性. \nComposite比较容易理解,想到 Composite 就应该想到\u003Cem\u003E树形\u003C\u002Fem\u003E结构图。组合体内这些对象都有共同接口,当组合体一个对象\n的方法被调用执行时,Composite 将遍历(Iterator)整个\u003Cem\u003E树形\u003C\u002Fem\u003E结构,寻找同样包含这个方法的对象并实现调用执行。可以用牵一\n动百来形容。 \n所以 Composite 模式使用到 Iterator 模式,和 Chain of Responsibility 模式类似。 \nComposite 好处: \n1.使客户端调用简单,客户端可以一致的使用组合结构或其\u003Cem\u003E中\u003C\u002Fem\u003E单个对象,用户就不必关系自己处理的是单个对象还是整个\n组合结构,这就简化了客户端代码。 \n2.更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。 \n如何使用 Composite? \n首先定义一个接口或抽象类,这是设计模式通用方式了,其他设计模式对接口内部定义限制不多, Composite 却有个规定,\n那就是要在接口内部定义一个用于访问和管理 Composite组合体的对象们(或称部件 Component). \n下面的代码是以抽象类定义,一般尽量用接口 interface, \npublic abstract class Equipment \n{ \nprivate String name; \n\u002F\u002F实价 \npublic abstract double netPrice(); \n\u002F\u002F折扣价格 public abstract double discountPrice(); \n\u002F\u002F增加部件方法 \npublic boolean add(Equipment equipment) { return false; } \n\u002F\u002F删除部件方法 \npublic boolean remove(Equipment equipment) { return false; } \n\u002F\u002F注意这里,这里就提供一种用于访问组合体类的部件方法。 \npublic Iterator iter() { return null; } \npublic Equipment(final String name) { this.name=name; } \n} \n抽象类 Equipment 就是 Component 定义,代表着组合体类的对象们,Equipment \u003Cem\u003E中\u003C\u002Fem\u003E定义几个共同的方法。 \npublic class Disk extends Equipment \n{ \npublic Disk(String name) { super(name); } \n\u002F\u002F定义 Disk 实价为 1 \npublic double netPrice() { return 1.; } \n\u002F\u002F定义了 disk 折扣价格是 0.5 对折。 \npublic double discountPrice() { return .5; } \n} \nDisk是组合体内的一个对象,或称一个部件,这个部件是个单独元素( Primitive)。 \n还有一种可能是,一个部件也是一个组合体,就是说这个部件下面还有'儿子',这是\u003Cem\u003E树形\u003C\u002Fem\u003E结构\u003Cem\u003E中\u003C\u002Fem\u003E通常的情况,应该比较容易理解。\n现在我们先要定义这个组合体: \nabstract class CompositeEquipment extends Equipment \n{ \nprivate int i=0; \n\u002F\u002F定义一个 Vector 用来存放'儿子' \nprivate Lsit equipment=new ArrayList(); \npublic CompositeEquipment(String name) { super(name); } \npublic boolean add(Equipment equipment) { \nthis.equipment.add(equipment); \nreturn true; \n} \npublic double netPrice() \n{ \ndouble netPrice=0.; \nIterator iter=equipment.iterator(); \nfor(iter.hasNext()) \nnetPrice+=((Equipment)iter.next()).netPrice(); \nreturn netPrice; \n} \npublic double discountPrice() \n{ \ndouble discountPrice=0.; \nIterator iter=equipment.iterator(); for(iter.hasNext()) \ndiscountPrice+=((Equipment)iter.next()).discountPrice(); \nreturn discountPrice; \n} \n\u002F\u002F注意这里,这里就提供用于访问自己组合体内的部件方法。 \n\u002F\u002F上面 dIsk 之所以没有,是因为 Disk 是个单独(Primitive)的元素. \npublic Iterator iter() \n{ \nreturn equipment.iterator() ; \n{ \n\u002F\u002F重载 Iterator 方法 \npublic boolean hasNext() { return i\u003Cequipment.size(); } \n\u002F\u002F重载 Iterator 方法 \npublic Object next() \n{ \nif(hasNext()) \nreturn equipment.elementAt(i++); \nelse \nthrow new NoSuchElementException(); \n} \n} \n上面 CompositeEquipment 继承了 Equipment,同时为自己里面的对象们提供了外部访问的方法,重载了\nIterator,Iterator 是 Java 的 Collection 的一个接口,是 Iterator 模式的实现. \n我们再看看 CompositeEquipment 的两个具体类:盘盒 Chassis 和箱子 Cabinet,箱子里面可以放很多东西,如底板,\n电源盒,硬盘盒等;盘盒里面可以放一些小设备,如硬盘 软驱等。无疑这两个都是属于组合体性质的。 \npublic class Chassis extends CompositeEquipment \n{ \npublic Chassis(String name) { super(name); } \npublic double netPrice() { return 1.+super.netPrice(); } \npublic double discountPrice() { return .5+super.discountPrice(); } \n} \npublic class Cabinet extends CompositeEquipment \n{ \npublic Cabinet(String name) { super(name); } \npublic double netPrice() { return 1.+super.netPrice(); } \npublic double discountPrice() { return .5+super.discountPrice(); } \n} \n至此我们完成了整个 Composite模式的架构。 \n我们可以看看客户端调用 Composote 代码: \nCabinet cabinet=new Cabinet(\"Tower\"); \nChassis chassis=new Chassis(\"PC Chassis\"); \n\u002F\u002F将 PC Chassis 装到 Tower \u003Cem\u003E中\u003C\u002Fem\u003E (将盘盒装到箱子里) \ncabinet.add(chassis); \u002F\u002F将一个 10GB 的硬盘装到 PC Chassis (将硬盘装到盘盒里) \nchassis.add(new Disk(\"10 GB\")); \n\u002F\u002F调用 netPrice()方法; \nSystem.out.println(\"netPrice=\"+cabinet.netPrice()); \nSystem.out.println(\"discountPrice=\"+cabinet.discountPrice()); \n上面调用的方法 netPrice()或 discountPrice(),实际上 Composite 使用 Iterator 遍历了整个\u003Cem\u003E树形\u003C\u002Fem\u003E结构,寻找同样包含这\n个方法的对象并实现调用执行. \nComposite是个很巧妙体现智慧的模式,在实际应用\u003Cem\u003E中\u003C\u002Fem\u003E,如果碰到\u003Cem\u003E树形\u003C\u002Fem\u003E结构,我们就可以尝试是否可以使用这个模式。 \n以论坛为例,一个版(forum)\u003Cem\u003E中\u003C\u002Fem\u003E有很多帖子(message),这些帖子有原始贴,有对原始贴的回应贴,是个典型的\u003Cem\u003E树形\u003C\u002Fem\u003E结构,\n那么当然可以使用 Composite模式,那么我们进入 Jive\u003Cem\u003E中\u003C\u002Fem\u003E看看,是如何实现的. \nJive 解剖 \n在 Jive\u003Cem\u003E中\u003C\u002Fem\u003E ForumThread 是 ForumMessages 的容器 container(组合体).也就是说,ForumThread 类似我们上例\u003Cem\u003E中\u003C\u002Fem\u003E的 \nCompositeEquipment.它和 messages 的关系如图: \n\n[thread] \n|- [message] \n|- [message] \n|- [message] \n|- [message] \n|- [message] \n我们在 ForumThread 看到如下代码: \npublic interface ForumThread { \n.... \npublic void addMessage(ForumMessage parentMessage, ForumMessage \nnewMessage) \nthrows UnauthorizedException; \npublic void deleteMessage(ForumMessage message) \nthrows UnauthorizedException; \npublic Iterator messages(); \n.... \n} \n类似 CompositeEquipment, 提供用于访问自己组合体内的部件方法: 增加 删除 遍历. \n结合我的其他模式\u003Cem\u003E中\u003C\u002Fem\u003E对 Jive的分析,我们已经基本大体理解了 Jive 论坛体系的框架,如果你之前不理解设计模式,而直接去看\nJive源代码,你肯定无法看懂。 \n参考文章: \nComposite 模式和\u003Cem\u003E树形\u003C\u002Fem\u003E结构的讨论 \n设计模式之 Decorator(油漆工) \n装饰模式:Decorator 常被翻译成\"装饰\",我觉得翻译成\"油漆工\"更形象点,油漆工(decorator)是用来刷油漆的,那么被刷油漆的\n对象我们称 decoratee.这两种实体在 Decorator 模式\u003Cem\u003E中\u003C\u002Fem\u003E是必须的. \nDecorator定义: \n动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用 Decorator 模式相比用生成子类方式达到功能的扩充显得更为灵\n活. 为什么使用 Decorator? \n我们通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性,\n同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的. \n使用Decorator的理由是:这些功能需要由用户动态决定加入的方式和时机.Decorator提供了\"即插即用\"的方法,在运行期间决\n定何时增加何种功能. \n如何使用? \n举Adapter \u003Cem\u003E中\u003C\u002Fem\u003E的打桩示例,在 Adapter \u003Cem\u003E中\u003C\u002Fem\u003E有两种类:方形桩 圆形桩,Adapter模式展示如何综合使用这两个类,在Decorator模\n式\u003Cem\u003E中\u003C\u002Fem\u003E,我们是要在打桩时增加一些额外功能,比如,挖坑 在桩上钉木板等,不关心如何使用两个不相关的类. \n我们先建立一个接口: \npublic interface Work \n{ \npublic void insert(); \n} \n接口 Work有一个具体实现:插入方形桩或圆形桩,这两个区别对 Decorator 是无所谓.我们以插入方形桩为例: \npublic class SquarePeg implements Work{ \npublic void insert(){ \nSystem.out.println(\"方形桩插入\"); \n} \n} \n现在有一个应用:需要在桩打入前,挖坑,在打入后,在桩上钉木板,这些额外的功能是动态,可能随意增加调整修改,比如,可能又需\n要在打桩之后钉架子(只是比喻). \n那么我们使用 Decorator 模式,这里方形桩 SquarePeg 是 decoratee(被刷油漆者),我们需要在 decoratee 上刷些\"油漆\",这\n些油漆就是那些额外的功能. \npublic class Decorator implements Work{ \nprivate Work work; \n\u002F\u002F额外增加的功能被打包在这个 List \u003Cem\u003E中\u003C\u002Fem\u003E \nprivate ArrayList others = new ArrayList(); \n\u002F\u002F在构造器\u003Cem\u003E中\u003C\u002Fem\u003E使用组合 new方式,引入 Work 对象; \npublic Decorator(Work work) \n{ \nthis.work=work; \nothers.add(\"挖坑\"); \nothers.add(\"钉木板\"); \n} \npublic void insert(){ \nnewMethod(); \n} \n\u002F\u002F在新方法\u003Cem\u003E中\u003C\u002Fem\u003E,我们在 insert 之前增加其他方法,这里次序先后是用户灵活指定的 \npublic void newMethod() \n{ \notherMethod(); \nwork.insert(); \n} public void otherMethod() \n{ \nListIterator listIterator = others.listIterator(); \nwhile (listIterator.hasNext()) \n{ \nSystem.out.println(((String)(listIterator.next())) + \" 正在进行\"); \n} \n} \n} \n在上例\u003Cem\u003E中\u003C\u002Fem\u003E,我们把挖坑和钉木板都排在了打桩 insert 前面,这里只是举例说明额外功能次序可以任意安排. \n好了,Decorator 模式出来了,我们看如何调用: \nWork squarePeg = new SquarePeg(); \nWork decorator = new Decorator(squarePeg); \ndecorator.insert(); \nDecorator 模式至此完成. \n如果你细心,会发现,上面调用类似我们读取文件时的调用: \nFileReader fr = new FileReader(filename); \nBufferedReader br = new BufferedReader(fr); \n实际上 Java 的 I\u002FO API 就是使用 Decorator 实现的,I\u002FO变种很多,如果都采取继承方法,将会产生很多子类,显然相当繁琐. \nJive \u003Cem\u003E中\u003C\u002Fem\u003E的 Decorator 实现 \n在论坛系统\u003Cem\u003E中\u003C\u002Fem\u003E,有些特别的字是不能出现在论坛\u003Cem\u003E中\u003C\u002Fem\u003E如\"打倒 XXX\",我们需要过滤这些\"反动\"的字体.不让他们出现或者高亮度显\n示. \n在 IBM Java 专栏\u003Cem\u003E中\u003C\u002Fem\u003E专门谈 Jive的文章\u003Cem\u003E中\u003C\u002Fem\u003E,有谈及 Jive\u003Cem\u003E中\u003C\u002Fem\u003E ForumMessageFilter.java 使用了 Decorator 模式,其实,该程序并\n没有真正使用 Decorator,而是提示说:针对特别论坛可以设计额外增加的过滤功能,那么就可以重组 ForumMessageFilter 作\n为 Decorator 模式了. \n所以,我们在分辨是否真正是Decorator模式,以及会真正使用Decorator模式,一定要把握好Decorator模式的定义,以及其\u003Cem\u003E中\u003C\u002Fem\u003E\n参与的角色(Decoratee 和 Decorator). \n设计模式之 Bridge \nBridge 模式定义 :将抽象和行为划分开来,各自独立,但能动态的结合。 \n任何事物对象都有抽象和行为之分,例如人,人是一种抽象,人分男人和女人等;人有行为,行为也有各种具体表现,所\n以,“人”与“人的行为”两个概念也反映了抽象和行为之分。 \n在面向对象设计的基本概念\u003Cem\u003E中\u003C\u002Fem\u003E,对象这个概念实际是由属性和行为两个部分组成的,属性我们可以认为是一种静止的,是\n一种抽象,一般情况下,行为是包含在一个对象\u003Cem\u003E中\u003C\u002Fem\u003E,但是,在有的情况下,我们需要将这些行为也进行归类,形成一个总的行\n为接口,这就是桥模式的用处。 \n为什么使用? \n不希望抽象部分和行为有一种固定的绑定关系,而是应该可以动态联系的。 \n如果一个抽象类或接口有多个具体实现(子类、concrete subclass),这些子类之间关系可能有以下两种情况: \n1. 这多个子类之间概念是并列的,如前面举例,打桩,有两个 concrete class:方形桩和圆形桩;这两个形状上的桩是并列的,\n没有概念上的重复。 \n2.这多个子类之\u003Cem\u003E中\u003C\u002Fem\u003E有内容概念上重叠.那么需要我们把抽象共同部分和行为共同部分各自独立开来,原来是准备放在一个接\n口里,现在需要设计两个接口:抽象接口和行为接口,分别放置抽象和行为. \n例如,一杯咖啡为例,子类实现类为四个:\u003Cem\u003E中\u003C\u002Fem\u003E杯加奶、大杯加奶、 \u003Cem\u003E中\u003C\u002Fem\u003E杯不加奶、大杯不加奶。 \n但是,我们注意到:上面四个子类\u003Cem\u003E中\u003C\u002Fem\u003E有概念重叠,可从另外一个角度进行考虑,这四个类实际是两个角色的组合:抽象 和\n行为,其\u003Cem\u003E中\u003C\u002Fem\u003E抽象为:\u003Cem\u003E中\u003C\u002Fem\u003E杯和大杯;行为为:加奶 不加奶(如加橙汁 加苹果汁). 实现四个子类在抽象和行为之间发生了固定的绑定关系,如果以后动态增加加葡萄汁的行为,就必须再增加两个类:\u003Cem\u003E中\u003C\u002Fem\u003E杯\n加葡萄汁和大杯加葡萄汁。显然混乱,扩展性极差。 \n那我们从分离抽象和行为的角度,使用 Bridge模式来实现。 \n如何实现?","createTime":"2011-05-30 14:13:49","dataReportQuery":"spm=1035.2023.3001.6557&utm_medium=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-4-3325262-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default&depth_1-utm_source=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-4-3325262-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default","dataReportClick":"{\"mod\":\"popu_645\",\"index\":\"4\",\"dest\":\"https:\u002F\u002Fdownload.csdn.net\u002Fdownload\u002Fyxbbbs283127372\u002F3325262\",\"strategy\":\"2~default~OPENSEARCH~Rate\",\"extra\":\"{\\\"utm_medium\\\":\\\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-4-3325262-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\\\",\\\"dist_request_id\\\":\\\"1713920331325_95453\\\"}\",\"spm\":\"1035.2023.3001.6557\"}","dataReportView":"{\"mod\":\"popu_645\",\"index\":\"4\",\"dest\":\"https:\u002F\u002Fdownload.csdn.net\u002Fdownload\u002Fyxbbbs283127372\u002F3325262\",\"strategy\":\"2~default~OPENSEARCH~Rate\",\"extra\":\"{\\\"utm_medium\\\":\\\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-4-3325262-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\\\",\\\"dist_request_id\\\":\\\"1713920331325_95453\\\"}\",\"spm\":\"1035.2023.3001.6557\"}","type":"download"},{"url":"https:\u002F\u002Fdownload.csdn.net\u002Fdownload\u002Fsunnybuer\u002F15117746","title":"C# Winform\u003Cem\u003E数据\u003C\u002Fem\u003E库应用设计(附开发案例","desc":"c#编程集合资料,不错的应用设计,另附一些开发案例的下载地址,欢迎大家下载学习。\n学习完本课程之后,我们需要达到以下目标:\n(1) 掌握基本的C#语法,熟练运用C#编写基本的程序逻辑。\n(2) 能够创建C#控制台应用程序并处理输入输出。\n(3) 掌握C#\u003Cem\u003E中\u003C\u002Fem\u003E的数组,并对数组进行相应的排序,查找操作。\n(4) 熟练使用C#的字符串对象。\n(5) 掌握Windows窗体应用程序的创建,能熟练使用常用的控件设计窗体界面。\n(6) 掌握MDI应用程序的开发步骤。\n(7) 了解ADO.NET的组成和工作原理。\n(8) 通过ADO.NET访问对C#项目开发全程实录视频教程(全10个案例):htt: \u002Fcnrdn com\u002FgCxC\n课程说明…\n第1章C#语法基础……\n核心技能部分\n1.1\nNet与C#概述.\n111Net与C#的产生与应用\n1.1.2 Visual studio\n10\n1.1.3创建C井应用程序\n12\n2C#语言基础\n16\n121变量与常量…16\n12.2运算符和表达式\n19\n123C#语言\u003Cem\u003E中\u003C\u002Fem\u003E的注释\n1.2.4使用 Console处理输入输出\n21\n1.3\nC#语句结构\n25\n131条件语句\n.25\n132循环结构\n32\n任务实训部分.…\n38\n1:根据时间输出问候信息……\n38\n2:三个数字比较大小\n39\n3:判断用户输入的字母\n.40\n输出裴波那契数列……\n翻着音\n40\n巩固练习\n第2章嵌套循环和数组.\n44\n核心技能部分…\n.45\n2.1\nVS2008\u003Cem\u003E中\u003C\u002Fem\u003E的调试技巧\n45\n2.2\n嵌套循环\n47\n2.3\n数组.\n50\n231数组的定义\n50\n232数组的基木操作\n50\n233数组的排序\n51\n任务实训部分…\n55\n1打印等腰三角形\n55\n2:数组的操作\n56\n3:数组的排序。\n错误!定义书签\n4:数组的排序\n错误!未定义书签\n巩固练习\n57\n第3章方法与字符串\n59\n\nC#项目开发全程实录视频教程(全10个案例):htt: \u002Fcnrdn com\u002FgCxC\n核心技能部分\n使用方法\n311方法的定义\n312方法的调用\n63\n313参数传递\nString类\n321C#语言\u003Cem\u003E中\u003C\u002Fem\u003E常用的字符串处理方法...\n68\n322格式字符串\n32.3 String Builder类.\n3.3\n类型转换…14\n331隐式转换\n74\n332显式转换.……\n74\n333常用类型转换方法…\n7\n任务实训部分\n77\n1:方法的使用\n2:从邮件地址提取用广名\n80\n3:网址类型分析\n81\n4:字符串转换\n82\n巩固练习.\n84\n第4章指导学习:阶段总结\n86\n知识总结\n翻着\n.:::a:a:.:::a:B:a:::::..aa:::.:.aa:.:aa:::\n86\n41.1核心技能目标\n86\n412知识体系总结…\n86\n4.2\n综合实训\n任务1:制作月份日历\n任务2:数组\u003Cem\u003E数据\u003C\u002Fem\u003E添加和排序.\n错误!未定义书签\n任务3:自杀游戏…\n错误未定义书签。\n第5章 Win form常用控件\n核心技能部分\n90\n创建 Windows应用稈序\n90\n511 Windows应用程序概述.\n90\n512创建第一个 Windows应用程序\n5.13项目结构分析\n5,2\nWindows窗体….97\n5.,21窗体\u003Cem\u003E中\u003C\u002Fem\u003E的常用属性.\n98\n522窗体\u003Cem\u003E中\u003C\u002Fem\u003E的常用事件……\n99\nWindows窗体\u003Cem\u003E中\u003C\u002Fem\u003E的常用控件\n9\n\nC#项目开发全程实录视频教程(全10个案例):htt: \u002Fcnrdn com\u002FgCxC\n5.31 Winform控件公共属性…\n532标签Labe)\n01\n533文本框( TextBox)\n·,,\n101\n534按钮( Button)…102\n535列表框 ListBox)\n102\n536组合框 Combobox)\n103\n53.7单选按钮( Radio Button)和复选框( CheckBox)\n104\n538图片框( Pictruebo×)..105\n54用 Message Box类\u003Cem\u003E显示\u003C\u002Fem\u003E消息窗口\n541消息框的\u003Cem\u003E显示\u003C\u002Fem\u003E……106\n5.4.2消息框的返回值\n107\n综合案例:职员信息管理.\n109\n仟务实训部分……\n115\n1:ATM信息查询\n115\n2:编写建表向导窗体……\n3:火车票预定程厅…\n124\n巩固练习…\n第6章\nMD窗体应用程序设计…\n核心技能部分……\n130\n6.1\nSD窗体和MD窗体应用程序简介.\n错误!未定义书签。\n6.2\n单文档应用程序的创建\n30\n62.1菜单栏( Menustrip)\n130\n622菜单栏的创建\n130\n623上下文菜单 ContextMenuStrip)\n6.3\n多文档应用程序\n错误!未定义书签。\n631创建多文档界面应用程序.\n错误!未定义书签\n632排列子窗口\n错误未定义书签。\n64图像列表( mageList控件…\n134\n65工具栏( ToolStrip控件)\n135\n66\n状态( StatusStrip)\n138\n67选项卡( TabControl\nTimer控件\n69\nMD综合示例\n错误!定义书签\n任务实训部分……143\n1创建记事本”应用程序\n错误!未定义书签\n2:增强”记事本”功能∴\n143\n3:实现记事本字体样式设置…\n144\n\nC#项目开发全程实录视频教程(全10个案例):htt: \u002Fcnrdn com\u002FgCxC\n4:变色窗体\n巩固练习………\n1448\n第7章\n使用 ADO. NET完成简单的\u003Cem\u003E数据\u003C\u002Fem\u003E库操作….\n·,,\n150\n核心技能部分\n151\nADO. NET概述\n151\n1 ADO.NET的简介\n151\n7.12 ADO.NET的优点\n152\n713 ADO.NET的结\n52\nNET Framework\u003Cem\u003E数据\u003C\u002Fem\u003E提供程序\n1154\n7.21 Connection对象…………………………155\n72.2使用 Connection对象链接到\u003Cem\u003E数据\u003C\u002Fem\u003E库\n7.3异常操作\n57\n731try和 catch块\n158\n732\u003Cem\u003E数据\u003C\u002Fem\u003E库链接示例\nCommand对象\n∴161\n741 Command对象简介\n161\n742 Command综合示例\n任务实训部分\n1:实现进销存系统用户注册\n168\n2:实现进销存系统用户登录.…\n171\n3:实现用户的删除功能……\n.:.::::::.:...:::.:.:a.::::.:::::::::.:::.:::::::.:::.:\n172\n巩固练习\n174\n第8章使用 Data Reader完成查询功能\n177\n核心技能部分…\n178\n8.1\nDataReader对象\n811 Data reader对象简介\n178\n812 Data Reader对象常用的属性和方法\n813 Data reader对象的使用\n179\n8.2\n控件\n81\n821 Listview控件介绍……\n81\n822 Listview控件的使用\n\u003Cem\u003E数据\u003C\u002Fem\u003E库操作综合示例\n187\n任务实训部分……\nL94\n1:使用 Listview控件查询部门员工信息…\n94\n2:部门员工信息删除和修改\n3:实现员工信息模糊查询...\n203\n巩固练习\n204\n\nC#项目开发全程实录视频教程(全10个案例):htt: \u002Fcnrdn com\u002FgCxC\n第9章\n使用 Dataset实现断开式\u003Cem\u003E数据\u003C\u002Fem\u003E访问\n206\n核心技能部分.…\n207\n91\u003Cem\u003E数据\u003C\u002Fem\u003E集( Dataset)\n·,,\n207\n911\u003Cem\u003E数据\u003C\u002Fem\u003E集( DataSet)简介…207\n912\u003Cem\u003E数据\u003C\u002Fem\u003E集的结构\n08\n91.3\u003Cem\u003E数据\u003C\u002Fem\u003E集的工作原理\n914创建 Data set对象……\n211\n9,2\nDataAdapter对象1211\n92.1 DataAdapter对象简介…\n211\n922 DataAdapter对象的使用..\n213\n3 Datagridview控什的使用\n219\n931 Data gridview控件简介\n219\n932 Datagridview控件的使用.\n221\n9\n综合示例\n226\n仟务实训部分.…\n229\n1:航班查询窗体设计\n29\n2:\u003Cem\u003E显示\u003C\u002Fem\u003E所有航班信息\n232\n3:根据两地査询航班\n.233\n4:航班详细信息查询\n234\n巩固练习\n235\n第10章课程总复习…\n…)误!未定义书签。\n101知识总结\n错误!未定义书签\n1011核心技能目标\n错误!定义书签。\n101.2知识体系总结\n错误!未定义书签。\n02任务实训\n错误!未定义书签。\n第11章项目案例:酒店管理系统……\n错误!未定义书签\n111训练技能点……\n错误未定义书签。\n112需求说明\n错误!未定义书签\n113设计与思路分析\n错误未定义书签\n113.1系统功能分析\n错误!未定义书签。\n1132\u003Cem\u003E数据\u003C\u002Fem\u003E库设计\n错误!定义书签。\n114实现步骤……\n错误!未定义书签\n115时间分配\n错误!定义书签\n\nC#项目开发全程实录视频教程(全10个案例):htt: \u002Fcnrdn com\u002FgCxC\n第1章C#语法基础\n学习内容\nc#的发展史\nC#的基本语法\nC#的流程控制语句\n俨能力目标\n掌握仗用S2008开发C#NET控制台应用程序\n掌握C#语言的基本语法\n掌握c#的程序流程控制语句\n\nC#项目开发全程实录视频教程(全10个案例):htt: \u002Fcnrdn com\u002FgCxC\n本章简介\n从本门课开始我们将要开始学习¢#语言和NET平台。本章将使学员对NET和¢#有一个\n初步的认识,了解C#的开发环境,编写第一个C#控制台应用程序。C#语言的基本语法和我\n们之前的学习的C语言、Java语言一样同属于C语言语法系列,有很多相似的地方,同时也\n有一些不同的地方,因此我们在学习的时候需要注意它们之间的区别,不要混淆。在本章\u003Cem\u003E中\u003C\u002Fem\u003E,\n我们需要掌握c#\u003Cem\u003E中\u003C\u002Fem\u003E的变量、\u003Cem\u003E数据\u003C\u002Fem\u003E类型、运算符、条件、分攴、循环等基C排基础语法,这些\n语言层血的知识是我们编写所有程序的基础,因此必须牢固掌握。\n核心技能部分\n1.1Net与C#概述\n1.1.1Net与C#的产生与应用\n1. Anders Hejlsberg-C#之父\nAnders hejlsberg原木是曾经大名鼎鼎的 Borland公司的一员,他曾经编写了 Pasca编译\n器,又把 Turbo pascal变为面向对象的 Object Pascal,并以此为基础开发了轰动全球、盛极\n时的廾发工具 Delphi,为 Boland公司赚了个盆钵满盈。\n随着 Delphi日渐成熟, Anders的兴趣转向了Java领域,他在」ava开发领域扩展方面有\n很多自己独特的想法,并想在此领域大展宏图,但 Borland的经营者们还要靠他这棵“摇\n钱树”继续在 Delphi上人肆捞金,所以他有一段郁郁不得志。\n比尔盖茨三顾茅庐,力邀 Anders hejlsberg,并许以重金和宽松的环境,终于把 Anders\n挖到了微软的旗下,其后由其主持设计,在2000年6月发布了新的开发语言C#(读做C\nSharp),此后微软在2002年推出了 Microsoft net开发平台。\n3 1.1.1 Anders He jlsberg\n\nC#项目开发全程实录视频教程(全10个案例):http:\u002F\u002Fcnrdn.com\u002Fgcxc\n2.C#语及其特点\n与Java一样,C#语言是一个完全的面向对象语言,它继承了C++、Java和 Delphi的优\n点,又借鉴了VB的简单易学。体现了当今最新的程序设计技术的功能和精华。C#继承了C\n语言的语法风柊,同时又继承了C+的面冋对象特性。不同的是,c#的对象模犁己经面向\nInternet进行了重新设计,使用的是NET框架的类库;C#不再提供对指针类型的支持,使得\n程序不能随便访问内存地址空间,从而更加健壮;C#不再支持多重继承,避免了以往类层次\n结构\u003Cem\u003E中\u003C\u002Fem\u003E由于多重继承带来的可怕后果。NET框架为C#提供了一个强大的、易用的、逻辑结\n构一致的程序设计环境。同时,公共语言运行时( Common Language runtime)为C#程序语\n言提供了一个托管的运行时环境,使程序比以往更加稳定、安全。其特点有:\n语言简洁。\n保留了C++的强大功能\n快速应用廾发功能\n语言的自由性\n强大的\u003Cem\u003EWeb\u003C\u002Fem\u003E服务器控件。\n支持跨平台\n与XML相融合\n如果之前没有其他话言的编程经验,使用c#语言编程将是一个良好的开端。如果有其\n他语言的编程基础,程序员将发现¢#语言除了像ⅤB一样简单易学外,还是一种拥有强大\n功能的语言。而且 ASP NET平台也是完仝通过c#语言开发的,这决定了C语言得天独厚的\n优势。但在任何情况下,C#语言都不可能孤立地使用,它必须同 Microsoft. net framework\n起使用,因为使用C#语言编写的所有代码总是在 Microsoft .net framework\u003Cem\u003E中\u003C\u002Fem\u003E运行。\n1.1.2 Visual studio\n微软针对Net推岀了功能强大的集成丌发环境来支持开发人员的№et应用程序丌发,这\n就是 Visual studio,它是目前最主要的Net平台开发环境。VS集成了 NET Framework和Net\n开发插件,可以用来进行几乎所有Net应用程序的设计和开发L作,如 Windows应用程序\n\u003Cem\u003EWeb\u003C\u002Fem\u003E应用稈序、 Windows服务、智能设备应用程序等。\n随着 NET Framework的不断升级, Visua| Studio也在不断升级,其发展历程可以用表1-1-1\n来说明\n表1-1-1Vs发展历程\n年代\n2002\n2003\n2005\n2008\n2010\n廾发工具版木Vs2002\nVS2003\nVS2005\nVS2008\nVS2010\nNet\n1.0\n1.1\n2.0\n3.5\n4.0\nFramework\n由于本学期的知识点主要集\u003Cem\u003E中\u003C\u002Fem\u003E在C#的基本语法、 Win forms开发和 ADO. NET,这些知识","createTime":"2021-02-07 13:30:42","dataReportQuery":"spm=1035.2023.3001.6557&utm_medium=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-5-15117746-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default&depth_1-utm_source=distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-5-15117746-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default","dataReportClick":"{\"mod\":\"popu_645\",\"index\":\"5\",\"dest\":\"https:\u002F\u002Fdownload.csdn.net\u002Fdownload\u002Fsunnybuer\u002F15117746\",\"strategy\":\"2~default~OPENSEARCH~Rate\",\"extra\":\"{\\\"utm_medium\\\":\\\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-5-15117746-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\\\",\\\"dist_request_id\\\":\\\"1713920331325_95453\\\"}\",\"spm\":\"1035.2023.3001.6557\"}","dataReportView":"{\"mod\":\"popu_645\",\"index\":\"5\",\"dest\":\"https:\u002F\u002Fdownload.csdn.net\u002Fdownload\u002Fsunnybuer\u002F15117746\",\"strategy\":\"2~default~OPENSEARCH~Rate\",\"extra\":\"{\\\"utm_medium\\\":\\\"distribute.pc_relevant_bbs_down_v2.none-task-download-2~default~OPENSEARCH~Rate-5-15117746-bbs-270024745.264^v3^pc_relevant_bbs_down_v2_default\\\",\\\"dist_request_id\\\":\\\"1713920331325_95453\\\"}\",\"spm\":\"1035.2023.3001.6557\"}","type":"download"}],"staffDOList":[{"id":null,"communityId":211,"username":"community_93","userNickname":"ASP.NET","roleCode":1,"status":1,"createUsername":"","updateUsername":"","avatarUrl":"https:\u002F\u002Fprofile-avatar.csdnimg.cn\u002Fdefault.jpg!1","createTime":"2021-05-12 18:07:05","updateTime":"2021-05-12 18:07:05","lastLoginTime":"2021-05-12 18:07:05"},{"id":null,"communityId":211,"username":"dotnetconf","userNickname":".Net开发者社区","roleCode":2,"status":1,"createUsername":"community_93","updateUsername":"","avatarUrl":"https:\u002F\u002Fprofile-avatar.csdnimg.cn\u002Fdefault.jpg!1","createTime":"2022-12-01 00:26:57","updateTime":"2022-12-01 00:26:57","lastLoginTime":"2022-12-01 00:26:57"},{"id":null,"communityId":211,"username":"weixin_41960540","userNickname":"R小R","roleCode":2,"status":1,"createUsername":"community_93","updateUsername":"","avatarUrl":"https:\u002F\u002Fprofile-avatar.csdnimg.cn\u002Faa17748a52c84d88ba031f9895a4ea32_weixin_41960540.jpg!1","createTime":"2022-04-16 21:18:57","updateTime":"2022-04-16 21:18:57","lastLoginTime":"2022-04-16 21:18:57"}],"communityConfig":{"scoreType":0,"scoreItems":{"0":"给本帖投票","1":"锋芒小试,眼前一亮","2":"潜力巨大,未来可期","3":"持续贡献,值得关注","4":"成绩优异,大力学习","5":"贡献巨大,全力支持"}},"shouldApply":false,"subscribeAble":false,"operatorAble":false,"commentNeedJoinCommunity":false},"default2014LiveRoom":[{"itemType":"","description":"高峰论坛","title":"2022 技术英雄会","url":"https:\u002F\u002Flive.csdn.net\u002Froom\u002Fiframe\u002Fcsdnnews\u002FfsNR5NWp?chat=1&title=1&footer=1","images":["https:\u002F\u002Fimg-home.csdnimg.cn\u002Fimages\u002F20221016050009.png"],"ext":{"time":"9:00","liveRoomUrl":"https:\u002F\u002Flive.csdn.net\u002Froom\u002Fcsdnnews\u002FfsNR5NWp"}}]},"isGooglebot":false,"canonical":"https:\u002F\u002Fwww.csdn.net\u002Ftopics\u002F270024745","openUrl":"","isApp":false,"localUrl":"https:\u002F\u002Fbbs.csdn.net\u002Ftopics\u002F270024745","typeId":"20680","hasIndex":false},"CFG":{"ALIPLAYER_VERSION":"v4","ALIPLAYER_H5_VERSION":"mobile_v1","ENV":"prod","ROOT_URL":"https:\u002F\u002Fcms-mall.csdn.net\u002F","VUE_APP_API_URL_SERVER":"http:\u002F\u002Fcms-community-api.internal.csdn.net\u002F","VUE_APP_API_URL":"https:\u002F\u002Fcms-api.csdn.net\u002F","LOGIN_URL":"https:\u002F\u002Fpassport.csdn.net\u002Faccount\u002Flogin","VUE_APP_DOMAIN_SKILL":"https:\u002F\u002Fedu.csdn.net\u002F","VUE_APP_DOMAIN_PATH":"https:\u002F\u002Fedu.csdn.net\u002F","VUE_APP_COMMUNITY_API_URL":"https:\u002F\u002Fcommunity-api.csdn.net\u002F","VUE_APP_CCLOUD_API_URL":"https:\u002F\u002Fbizapi.csdn.net\u002Fcommunity-cloud\u002Fv1\u002F","VUE_APP_SKILL_API_URL":"https:\u002F\u002Fbizapi.csdn.net\u002Fskilltree\u002Fapi\u002F","VUE_APP_SEARCH_PLUGIN_API_URL":"https:\u002F\u002Fbizapi.csdn.net\u002Fsearchplugin\u002F","VUE_APP_COMMUNITY_ASK_API_URL":"https:\u002F\u002Fmp-ask.csdn.net\u002F","VUE_APP_ME_URL":"https:\u002F\u002Fme.csdn.net\u002F","VUE_APP_CCLOUD_RESUME":"https:\u002F\u002Fbizapi.csdn.net\u002Fjob-api\u002F","VUE_APP_CCLOUD_MAIN":"https:\u002F\u002Fwww.csdn.net\u002F","VUE_APP_CCLOUD_UC":"https:\u002F\u002Fwww.csdn.net\u002F","VUE_APP_CCLOUD_BZP_API_URL":"https:\u002F\u002Fbizapi.csdn.net\u002F","VUE_APP_CCLOUD_START_API_URL":"https:\u002F\u002Fmp-action.csdn.net\u002F","VUE_APP_PRACTIVE":"https:\u002F\u002Fbizapi.csdn.net\u002Fdaily-practice\u002F","VUE_APP_CCLOUD_HOSTPATH":"https:\u002F\u002Fbbs.csdn.net\u002F"},"queries":{"pageId":[],"domain":["ccloud.csdn.net\u002Fccloud\u002Fdetail1"],"id":["270024745"],"deviceType":"pc","isSpider":"","hostname":["bbs.csdn.net"]},"basePath":"bbs.csdn.net\u002Fccloud\u002Ftopics\u002F270024745","hrefUrl":"https:\u002F\u002Fbbs.csdn.net\u002Ftopics\u002F270024745","active":0,"navBarFixed":false,"title":"如何在netweb中让数据树形显示","isLive":false,"contentType":{"text":"text","picture":"picture","link":"link","video":"video","vote":"vote","live":"live","blog":"blog","long_text":"long_text","task_text":"task_text"},"liveUrl":"https:\u002F\u002Flive.csdn.net\u002Froom\u002Fiframe\u002F","spmExtra":{"id":211,"topicId":270024745},"keywords":"","description":"以下内容是CSDN社区关于如何在netweb中让数据树形显示相关内容,如果想了解更多关于.NET社区社区其他内容,请访问CSDN社区。"};</script><script type="text/javascript" src="https://csdnimg.cn/release/cmsfe/public/js/runtime.3e5c09eb.js"></script><script type="text/javascript" src="https://csdnimg.cn/release/cmsfe/public/js/chunk/common.7672e502.js"></script><script type="text/javascript" src="https://csdnimg.cn/release/cmsfe/public/js/chunk/tpl/ccloud-detail/index.243a94d0.js"></script></body> <!----> <script> window.csdn.sideToolbar = { options: { qr: { isShow: true, data: [ { imgSrc: 'https://csdnimg.cn/release/cmsfe/public/img/ewm.9010d6e5.png', desc: "关注公众号" }, ] }, help: { isShow: false, }, contentEl: document.getElementsByClassName("cloud-maintainer")[0] }, }; </script> <script src="https://g.csdnimg.cn/side-toolbar/2.9/side-toolbar.js" ></script> <!----> <!----> <!----> <script src="https://csdnimg.cn/release/blog_editor_html/release1.7.5/ckeditor/plugins/codesnippet/lib/highlight/highlight.pack.js"></script> <script src="https://g.csdnimg.cn/lib/editor-page-detail/v2.2.0/js/runDetail.min.js"></script> <!----> <!----> <!----> <!----> <!----> <!----> <script src="https://g.csdnimg.cn/collection-box/2.1.0/collection-box.js"></script> <!----> <!----> <!----> <!----> <script src="https://g.csdnimg.cn/common/csdn-cert/csdn-cert.js"></script> <!----></html>