完美解决在ModalPopupExtender中使用CalendarExtender时被层遮挡的问题

  ASP.NET AJAX Control Toolkit是一组非常不错的基于asp.net的ajax控件,它建立在asp.net 3.0的ScriptManager组件之上,提供了很多非常实用的效果和功能。大家可以去官方网站查看demo,ModalPopupExtender控件用来在网页中实现类似于模式对话框的效果,而CalendarExterder控件提供日期输入,它有几个很重要的属性:

  • TargetControlID:日期输入的目标控件ID,一般来说都都是一个文本框。
  • Format:日期格式,如yyyy-MM-dd。
  • PopupButtonID:用户打开日期选择面板的控件ID,如按钮,图片等。
  • PopupPosition:设置日期选择面板打开的位置,这个是相对于TargetControlID所在控件的位置的。有几个可选的值:BottomLeft,BottomRight,Left,Right,TopLeft,TopRight。

  一般来说我们只需要设置这几个属性就可以满足应用了,除非你想自定义日期选择面板的显示样式,这时你需要自己给定CssClass。这里是一个例子。

< asp:TextBox ID ="tbBeginTime" runat ="server" CssClass ="singleText" MaxLength ="10" Width ="90" ></ asp:TextBox >
< asp:Image ID ="imgBeginTime" ImageUrl ="http://www.cnblogs.com/Images/Admin/Calendar_scheduleHS.png" runat ="server"   />
< ajaxToolkit:CalendarExtender ID ="CalendarExtenderBeginTime" Format ="yyyy-MM-dd" TargetControlID ="tbBeginTime" PopupButtonID ="imgBeginTime" runat ="server" >
</ ajaxToolkit:CalendarExtender >

  网上有人说这个控件打开的日期选择面板会被下拉列表挡住,好像在早期的版本中会存在这个问题,现在新的版本已经修正了这个bug。我所遇到的问题是在ModelPopupExtender控件中使用CalendarExtender,日期选择面板会被后面的ModelPopupExtender挡住。有关ModelPopupExtender的使用读者可以看看官方网站的例子,很简单,这里我就不多说了。看一下问题的截图。

2009-11-24 9-52-45

   看到了吧!CalendarExtender弹出的日期选择面板被后面的ModelPopupExtender挡住了。我在Google上搜了一些资料,大多都是讲怎么重新设置CalendarExtender控件的样式,指定层的z-inde属性等,但我尝试过都失败了,其中有人说在IE6下测试是可以的,不过我没有验证过,因为我现在也找不到装有IE6的机器了,没有环境,自然测不了。

  其实在FireFox下用Firebug查看页面生成的html,你会看到ModelPopupExtender样式中的z-index和CalendarExtender是相同的,这估计是Ajax Toolkit控件中的一个bug,应该所有类似于这样的控件都会存在这个问题,即在层上打开层,后打开的层会被之前的层挡住,因为它们的z-index都是相同的。想要日期输入面板不被后面的“模式对话框”挡住,只能是将它的z-index设得更大点,但是单纯的css修改又没有效果,因为这个日期输入面板是动态生成的,伴随着里面的css,所以你预先设置它的样式是没有用的,除非你修改控件的源代码。

  后来在网上查到了一个资料,其实CalendarExtender控件有几个客户端事件可以用,其中有一个OnClieckShown,是在日期输入面板打开后触发的,于是我们可以从这里下手,通过脚本来设置z-index的值。下面是代码。

< script type = " text/javascript " >
    
//  Ensure the calendar panel was shown on the top level.
     function  calendarShown(sender, args) { sender._popupBehavior._element.style.zIndex  =   1000005 ; }
< / script>

  原本ModelPopupExtender的z-index值就已经很高了,这恐怕是控件的设计者担心它会被其它层挡住的原因吧。我们将日期选择面板的z-index值再设高一点,然后在控件中添加OnClientShown="calendarShown",保存后重新查看页面。

2009-11-24 9-54-36

  一切搞定!看来CalendarExtender控件提供的几个脚本事件还是很有用的,读者可以自己去研究下其它几个脚本事件的用途。还有一个需要注意的地方,CalendarExtender控件虽然提供了一个非常棒的日期输入功能,但是它本身并不对目标控件中的值进行验证。例如那个文本框,用户是可以手动填写内容的,这时CalendarExtender并不对其中的值进行校验,除非你将文本框设置为只读,这时又会有一个问题,那就是用户如何清除里面的值呢?看来还需要自己写代码验证一下文本框里的值。结合上面给出的代码,我们可以在给文本框添加一个客户端onblur事件,当它失去焦点的时候,验证其中的值。下面是用来进行验证的js代码。
function  CheckDate(Inobj) {
    Inobj.value 
=  trim(Inobj.value);
    
if  (Inobj.value  !=   "" ) {
        
var  reg  =   / ^\d{8}$ / ;
        
if  (Inobj.value.match(reg)  !=   null ) {
            Inobj.value 
=  Inobj.value.substring( 0 4 +   " - "   +  Inobj.value.substring( 4 6 +   " - "   +  Inobj.value.substring( 6 8 );
        }
        reg 
=   / ^([1-2]\d{3})-(([1][0-2])|(0?[1-9]))-(([3][0-1])|([1-2][0-9])|(0?[1-9]))$ / ;
        
if  (Inobj.value.match(reg)  ==   null ) {
            alert(
" 输入日期的格式不正确! " );
            Inobj.value 
=   "" ;
            Inobj.focus();
        }
    }
}

// 移除字符串中的空格
function  trim(s) {
    
var  s2 = "" ;
    
for (i = 0 ;i < s.length;i ++ ) {
        
if (s.charAt(i) != "   " ) s2 = s2 + s.charAt(i);
    }
    
return  s2;
}
  然后在文本框中添加onblur="CheckDate(this);"。这样,当用户输入非法值后,程序提示用户然后清空其中的值。

你可能感兴趣的:(calendar)