扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者:中国IT实验室 来源:中国IT实验室 2007年10月2日
关键字:
三、 构建复合控件―ListMover
这个ListMover控件包含两个EnhancedListBox控件,还有一些按钮用于在两个列表之间来回移动项。借助于这些复合控件构建技术,你可以学习如何创建子控?⑶沂褂靡恍?TML生成它们,最终的控件看上去如图2所示。对于这个控件,你要注意的是某些事情必须发生的位置。
图2.这个ListMover控件提供了一种标准方式让用户在两个列表间移动项。
首先,借助于与在以前的控件中相同的技术,你必须把在这个控件中需要的JavaScript代码添加到OnInit事件的重载版本中。列表7显示了你需要的JavaScript代码。如你在上一个控件中所做的一样,你也是使用JavaScript存取一个ListBox(<select>元素)中的元素。而且,我已经编制了函数分别实现把项添加到一个列表,从一个列表中删除项,以及从一个列表中添加或删除所有项。
我已经进行了功能的分离,而不是创建单个“move”方法;这样以来,我可以实现基于属性设置而使得从一个列表中删除项成为可选的。毫无疑问,这可以使最终的控件更为强壮些,但是我在本文中不再分析这些代码。还应该注意,就象在前面控件中一样,我也添加了一个BuildItemList方法。
现在,你需要把这一客户端代码依附到复合控件的按钮中。你可以在CreateChildControls方法的最后完成这一点;并且,在此时,完成子控件的初始化和构建控件集合。在此,我仅向你展示相应于一个按钮的代码(另外的按钮代码与此类似,省略)。
string s_AddToLeft = "AddSelectedItemToList(document.all." +
this.lstItemsOnRight.ClientID + ", document.all."
+ this.lstItemsOnLeft.ClientID + ", " +
(this.AllowDuplicatesOnLeft ? "true" : "false") + "); ";
string s_RemoveFromRight = "RemoveSelectedItemFromList(document.all." +
this.lstItemsOnRight.ClientID + "); ";
string s_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
+ " return false");
注意,我实现了在以前的控件中同样的工作。我把JavaScript函数调用构建成一字符串并且把它们依附到一个按钮上。主要区别在于,既然这是一个包含其它控件的复合控件,那么你可能使用把代码添加到onclick事件的Attributes.Add方法,这与在一个生成控件中把它放到一个栈上的方法形成对照。还要注意,我把多个功能放到onclick属性中;而且,函数调用的最后返回false以便取消按钮将执行的任何回寄。
最后,代码将在一个对Render重载的方法中初始化对客户端函数BuildItemList的调用。这看起来很象我在EnhancedListBox控件中向你介绍的那个,在此不再重复。注意,在这个控件中,我注册了两个隐藏的文本域,每一个相应于一个ListBox。
protected override void OnPreRender(EventArgs e)
{
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方法,因此在某处调用了它的基类。现在,既然你要从头编写一个复合控件,那么就没有基类可调用,而仅需提供你自己的方法实现。
这个控件的最后版本包含若干新的属性:包括用来决定是否添加到一个列表中的项能够被从另一个列表中删除的属性(如果一个列表将允许出现重复项的话);它还包含可扩展的风格化以实现最大化重用的目的,等等。
就这些。你已经使用了可用于客户端脚本中的隐藏的文本域来存储列表框的状态。在回寄期间,你使用隐藏文本域的内容来与服务器端项集合重新同步。最终结果是一个漂亮的复合控件―允许你在没有服务器回寄的情况下实现各列表项间的来回移动,而当一个回寄真正发生时仍能够保持这种变化。
四、 取二者最优
前面我没有提及的一个细节是为什么我在本文中混合了两个控件。文章一开始,我首先向你展示了一个标准ListBox控件的增强版本,然后把这个增强控件的两个实例应用于ListMover控件,而没有使用两个标准ListBox控件来构建这个ListMover。在本文中,我没有涉及的是ListMover控件的属性部分,它们将负责映射添加到EnhancedListBox控件上的属性。通过这种方式,我就能够从包含两个EnhancedListBox控件的ListMover控件中控制两个EnhancedListBox控件的增强功能。因此,你可以看到,你拥有结合了两个控件的最好的功能―你有了一个ListMover控件,它允许你在两个列表或单个列表的各项之间进行项的移动与重排序。
其实,这里真正关键的地方在于面向Web控件的ASP.net开发―完全封装。本文中的EnhancedListBox控件包含实现其目标(对它的项进行重排序)的所有代码。当我把两个这种控件包括在一个ListMover控件中时,我可以使用所有伴随着它们的智能性作为新控件的额外功能,包括每一个控件含有的客户端脚本以及在EnhancedListBox控件中的客户端到服务器的同步功能。因此,这个ListMover控件只需注意其自己的功能。图3展示了和EnhancedListBox控件在一起的ListMover控件,其中重排序按钮处于开状态。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者