马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
我认为,可以通过更加简单的首次编译,而增加第二次编译的负担,来提高java的运行效率。只是将java源代码进行简单的等价转换,而不假设编译成某种虚拟机器的目标格式,而由本地编译器针对性的二次编译。asp.net|初级 1、增添EnhancedListBox的客户端功效
为了利用客户端代码完成EnhancedListBox中项的重排序,你必需利用JavaScript剧本,而且要把它们依靠到EnhancedListBox的两个按钮上。为此,我倡议你利用“今后思索”的办法。就象编写一个老式的ASP之前的Web页面,起首编写一些天生HTML文件的JavaScript。为此,最好的办法是运转该控件,然后察看其源码并把它的HTML代码复制到一个编纂器,再增加JavaScript。列表2(见下载源代码)展现了你必要增加到你的控件中的JavaScript的原始情势。然后,借助于StringBuilder/StringWriter手艺(参考源码列表3),该控件构建这部分代码。该JavaScript代码由两部分功效构成:吸收一个HTML控件(在本例中是一个<select>控件);利用选择索引而且在列表中高低挪动它(基础上与我在本文入手下手我利用服务器代码向你展现的一样)。如今,你要了解,你把该JavaScript代码增加到Web控件的那边。为了完成在一个Web表单上有多个EnhancedListBox控件的情形下,该JavaScript代码不会被反复复制,你必要利用Page.ClientScript工具的RegisterClientScriptBlock办法输入它。
要使这个办法起感化,你必需在重载的OnInit事务中挪用它(见源码中列表4)。
最初,为使按钮准确事情,你必要把增加的客户端办法依靠到其上。在列表1中的代码中,你会看到援用了一个办法RenderButtons。只管我没有把该代码在此列出(请参考本文响应源码),可是它可以利用我在之前文章中先容的手艺天生按钮。事先,在天生实践HTML标签的之前,标签属性是利用AddAttribute办法以栈式寄存的。在此,你利用一样的手艺把客户端办法依靠到你的按钮。
strings_MoveUp="MoveItemUp(document.all."+this.ClientID+");
output.AddAttribute(HtmlTextWriterAttribute.OnClick,s_MoveUp);
记着,MoveItemUp是你已编写乐成的JavaScript函数之一。在天生用于排序的按钮之前,该代码将以仓库寄存这些JavaScript命令。关于向下(down)按钮,你利用一样的手艺。注重,我利用ClientId代表该天生后的控件的ID;可是,在这个控件位于一个复合控件外部时,这个属性要思索利用父控件的名字。
如今,你能够乐成地把该控件使用于一个Web表单中。你可使用与你操纵一个尺度ListBox控件一样的体例在其上增加一些项。
现实上,这完整是一个投放地位占位符(或ASP.NETListBox控件)。当你利用重排序按钮时,你将看到列表中的项响应地改动按次。如今让我们先记下这个成绩。假如你把一个按钮拖动到一个Web表单上(不必要为之增加代码)并实行一个回寄,你猜会产生甚么呢?完整与我之前形貌的一样;任何你利用重排序按钮作的重排序改动都将恢复到在比来一次回寄之前该控件看上往的形态。因而,让我们修正一下这个成绩。
起首,我再增加一些JavaScript(源码列表5)。注重,这部分代码被增加到重载的OnInit办法中而且利用StringBuilder/StringWriter手艺举行构建;并且,这个JavaScript办法的名字是BuildItemList。这个函数卖力构建列表框完全内容的一个字符串形貌而且把该串放到要传送到该函数的一个HTML元素的value属性中。你能够把这看做是列表内容的一种串行化。该串行化的输入作风会依据你本人的计划的分歧而有所分歧。挪用这个JavaScript函数必要依靠到该按钮上的别的代码。
strings_MoveUp="MoveItemUp(document.all."+this.ClientID+");";
strings_BuildItemList="BuildItemList(document.all."+this.ClientID+
",document.all.__"+this.ClientID+");";
output.AddAttribute(HtmlTextWriterAttribute.Onclick,MoveUp+""+BuildItemList);
如今,让我们来剖析一下你发送到BuildItemList函数的两个参数。第一个参数响应于天生的控件(<select>标签)的ID。第二个参数是别的一个ID,与前一个定名分歧,可是后面有一个"__"。这是一个你仍旧必要增加到你的Web控件的埋没的文本框,它将作为一个“串行化”项列表的占位符。我要在OnPreRender事务中注册这个埋没的文本域。
protectedoverridevoidOnPreRender(EventArgse)
{
base.OnPreRender(e);
if(Page!=null)
{
Page.ClientScript.RegisterHiddenField("__"+this.ID,"");
}
} 注重,我已利用我们的控件的ID来标识埋没的文本域。
到今朝为止,你已具有了一个完全功效的Web控件;个中,客户端JavaScript被绑定到个中的两个按钮上。该JavaScript乐成地完成在ListBox中的项的重排序而且把其内容串行化为一个字符串;然后,该字符串被存储在一个埋没的文本域中。一切这些都产生在客户端。假如一个回寄产生,不会产生重排序,由于当重排序时控件的Item服务器属性还没有收到你对它作的任何改动的动静;可是侥幸的是,位于埋没的文本域中的表单的一个串行化快照中产生了这一变更。如今,你有了能够与Item属性一同利用的内容了。那末,接上去,你该怎样完成呢?
<P> 2、同步
为了在第一次回寄和一切随后的回寄中完成同步,ASP.NET在IPostBackDataHandler接口的完成中供应了一个LoadPostData办法。在每次回寄时都要挪用这个LoadPostData办法;因而,你必要在此做一些事情。
值得一提的是,ASP.NET2.0修整了一个在1.1版本中被无视的小中央,但是这一修正可以使你的事情简单很多。ASP.NETListBox控件已在两个版本(1.1和2.0)中完成了IPostBackDataHandler接口。可是在2.0版本中,微软使这个接口的办法界说假造化(virtual,在VB中称作Overridable)。这意味着,你不用在EnhancedListBox控件中从头完成这个接口;而是,你仅需重载LoadPostData办法。
更主要的是,这也意味着,你能够存取基类完成而不用创立一切已存在于你的扩大控件中的功效。甚么功效呢?这包含微软加于个中的统统:用于处置Item汇合,SelectedIndex,SelectedValue和SelectedItem属性,及别的很多实行ListBox控件功效的代码。在ASP.NET1.1中,你必需在你的派生控件中完成这个接口而且要供应你本人对这两个办法的界说代码,不但包含你本人的到场的代码并且还要反复微软已在其把持中所完成的统统。
我推测,微软有人已发明了他们的完成中的毛病,而且把办法变成virtual的,如许开辟者可以存取基类的代码。因而,在源码列表6中向你展现怎样完成重载的LoadPostData办法。在这个重载中,你将起首挪用基类完成代码;然后,加上你必要的代码以与Item汇合同步。
别的,你还能够使用ListBox控件―经由过程把它编写成一个复合控件。此时,你必要把ListBox中的每个属性映照到你的EnhancedListBox以便使它成为ListBox控件的一个投放地位点位符。不管利用哪种办法,大概经由过程LoadPostData办法的从头创立,你都仍旧必要写良多代码。假如我专门为ASP.NET1.1编写这个控件,那末我极可能接纳最间接的计划:复合控件计划。
LoadPostData办法使你可以存取寄送到服务器的每个域,包含你的埋没文本域(存储在要传送到这个办法的postCollection参数中)。你能够问:为何必要该埋没文本域,而不是利用这个参数来存取被回寄的<select>元素呢?如今,我作一下注释。起首,回忆一下典范的ASP时期,事先你利用Request.Form属性来存取页面域。在回寄时,你可以存取一个<select>元素的独一的部分是选择的项。在该计划中,你必要完全的列表内容(因而,包含埋没的文本域)。列表6向你展现怎样剖析该埋没的文本域的内容而且把Item从头增加到Item汇合中。注重,你是如何挪用基类完成的。
最初,在你第一次天生控件时,你必需构建这个埋没的文本域,以防在任何重排序前产生页面回寄。Render办法的最初一行是:
output.Write("<scriptlanguage=javascript>BuildItemList(document.all."+this.ClientID+",document.all.__"+this.ClientID+");</script>");
你能够在列表1的最初看到这一点。
如今,你可使用EnhancedListBox控件来重排序一些项,回寄,而且确保在从头天生页眼前,控件的服务器存储与在客户端被改动的客户端存储完整同步。因而,如今让我们利用不异的手艺来构建一个复合控件ListMover。
<P> 3、构建复合控件―ListMover
这个ListMover控件包括两个EnhancedListBox控件,另有一些按钮用于在两个列表之间往返挪动项。借助于这些复合控件构建手艺,你能够进修怎样创立子控件而且利用一些HTML天生它们,终极的控件看上往如所示。关于这个控件,你要注重的是某些事变必需产生的地位。
.这个ListMover控件供应了一种尺度体例让用户在两个列表间挪动项。
起首,借助于与在之前的控件中不异的手艺,你必需把在这个控件中必要的JavaScript代码增加到OnInit事务的重载版本中。列表7显现了你必要的JavaScript代码。如你在上一个控件中所做的一样,你也是利用JavaScript存取一个ListBox(<select>元素)中的元素。并且,我已体例了函数分离完成把项增加到一个列表,从一个列表中删除项,和从一个列表中增加或删除一切项。
我已举行了功效的分别,而不是创立单个“move”办法;如许以来,我能够完成基于属性设置而使得从一个列表中删除项成为可选的。毫无疑问,这可使终极的控件更加健壮些,可是我在本文中不再剖析这些代码。还应当注重,就象在后面控件中一样,我也增加了一个BuildItemList办法。
如今,你必要把这一客户端代码依靠到复合控件的按钮中。你能够在CreateChildControls办法的最初完成这一点;而且,在此时,完成子控件的初始化和构建控件汇合。在此,我仅向你展现响应于一个按钮的代码(别的的按钮代码与此相似,省略)。
strings_AddToLeft="AddSelectedItemToList(document.all."+
this.lstItemsOnRight.ClientID+",document.all."
+this.lstItemsOnLeft.ClientID+","+
(this.AllowDuplicatesOnLeft?"true":"false")+");";
strings_RemoveFromRight="RemoveSelectedItemFromList(document.all."+
this.lstItemsOnRight.ClientID+");";
strings_BuildItemList="BuildItemList(document.all."+
this.lstItemsOnRight.ClientID+",document.all.__"+lstItemsOnRight.ClientID+");"+"BuildItemList(document.all."+this.lstItemsOnLeft.ClientID+",document.all.__"
+lstItemsOnLeft.ClientID+");";
this.btnAdd.Attributes.Add("onclick",s_AddToLeft
+""+s_RemoveFromRight+""+s_BuildItemList
+"returnfalse");
注重,我完成了在之前的控件中一样的事情。我把JavaScript函数挪用构建成一字符串而且把它们依靠到一个按钮上。次要区分在于,既然这是一个包括别的控件的复合控件,那末你大概利用把代码增加到onclick事务的Attributes.Add办法,这与在一个天生控件中把它放到一个栈上的办法构成对比。还要注重,我把多个功效放到onclick属性中;并且,函数挪用的最初前往false以便作废按钮将实行的任何回寄。
最初,代码将在一个对Render重载的办法中初始化对客户端函数BuildItemList的挪用。这看起来很象我在EnhancedListBox控件中向你先容的谁人,在此不再反复。注重,在这个控件中,我注册了两个埋没的文本域,每个响应于一个ListBox。
protectedoverridevoidOnPreRender(EventArgse)
{
base.OnPreRender(e);
if(Page!=null)
{
Page.ClientScript.RegisterHiddenField("__"+this.lstItemsOnRight.ClientID,
"");
Page.ClientScript.RegisterHiddenField("__"+this.lstItemsOnLeft.ClientID,
"");
Page.RegisterRequiresPostBack(this);
}
}
如今,你已构建乐成该复合控件,可以供应一些客户端JavaScript,而且把它绑定到按钮上。与之前一样,你能够把它放到一个表单上而且利用它;可是,在你增加同步代码之前,它仍将会碰到你在第一个控件中所碰到的成绩―你能够前后挪动项,可是一旦你初始化一个回寄(经由过程表单上的任何别的控件),该控件就会恢复到它回寄之前的形态。
为了修正这个成绩,你要完成你在第一个控件中所做的一样的事情。但是,既然你在开辟一个复合控件,而不是扩大一个已现有的控件,那末你必要完成IPostBackDataHandler接口而且供应LoadPostData和RaisePostDataChangedEvent办法的完成代码。这些完成(见列表7)与后面的控件基础分歧,除你要完成两个EnhancedListBox控件中的项汇合的同步而不是只思索一个控件外。而且与之前一样,你必要确保你保留你的SelectedIndex地位;如许以来,在你完成项汇合的同步后你就能够把它们设置归去。还要注重,在第一个控件中,你重载了基控件的LoadPostData办法,因而在某处挪用了它的基类。如今,既然你要重新编写一个复合控件,那末就没有基类可挪用,而仅需供应你本人的办法完成。
这个控件的最初版本包括多少新的属性:包含用来决意是不是增加到一个列表中的项可以被从另外一个列表中删除的属性(假如一个列表将同意呈现反复项的话);它还包括可扩大的作风化以完成最年夜化重用的目标,等等。
就这些。你已利用了可用于客户端剧本中的埋没的文本域来存储列表框的形态。在回寄时代,你利用埋没文本域的内容来与服务器端项汇合从头同步。终极了局是一个大度的复合控件―同意你在没有服务器回寄的情形下完成各列表项间的往返挪动,而当一个回寄真正产生时仍可以坚持这类变更。
<P> 4、取两者最优
后面我没有说起的一个细节是为何我在本文中夹杂了两个控件。文章一入手下手,我起首向你展现了一个尺度ListBox控件的加强版本,然后把这个加强控件的两个实例使用于ListMover控件,而没有利用两个尺度ListBox控件来构建这个ListMover。在本文中,我没有触及的是ListMover控件的属性部分,它们将卖力映照增加到EnhancedListBox控件上的属性。经由过程这类体例,我就可以够从包括两个EnhancedListBox控件的ListMover控件中把持两个EnhancedListBox控件的加强功效。因而,你能够看到,你具有分离了两个控件的最好的功效―你有了一个ListMover控件,它同意你在两个列表或单个列表的各项之间举行项的挪动与重排序。
实在,这里真正关头的中央在于面向Web控件的ASP.NET开辟―完整封装。本文中的EnhancedListBox控件包括完成其方针(对它的项举行重排序)的一切代码。当我把两个这类控件包含在一个ListMover控件中时,我可使用一切陪伴着它们的智能性作为新控件的分外功效,包含每个控件含有的客户端剧本和在EnhancedListBox控件中的客户端到服务器的同步功效。因而,这个ListMover控件只需注重其本人的功效。展现了和EnhancedListBox控件在一同的ListMover控件,个中重排序按钮处于开形态。
.经由过程组合ListMover和EnchancedListBox控件,你供应给用户的是具有两个列表的一个完全的控件,如许你能够完成在一个列表中或两个列表的各项间举行挪动。
最初,我激烈勉励你下载本文完全的源码举行研讨。既然我编写这些控件,那末我已屡次利用过ListMover,并且EnhancedListBox控件在我的一切工程开辟中几近能够交换尺度的ASP.NETListBox控件。
5、小结
我在本文中向你展现了怎样在一个Web控件内坚持在服务器和客户端之间的同步,并且这里所利用的手艺能够合用于很多相似的情形。只管ASP.NET2.0中引进了一个直不雅的接口用以处置剧本回调,可是,使功效完整位于客户端则是一种最快的办理计划并且可以与ASP.NET1.1坚持兼容。说其实的,我更对ASP.NET2.0中内置的回调才能感乐趣,请你也一同研讨吧。我实在想不明白java的机制,为什么非要那么蛋疼,在同一个平台下重复编译。 |