20080813 - TextBox 类 ReadOnly 属性脚本不兼容问题


最近做了一个.Net系统升级项目。从ASP.NET 1.1 升级到 ASP.NET 2.0/3.5,开始发现不兼容的都是第三方控件,等升级完毕后,才戏曲性的发现,兼容性产生的问题大多来自 .Net Framework 本身。比如 TextBox 类 ReadOnly 属性的脚本不兼容问题。

在 ASP.NET 1.1 项目中,可能会经常会用到选择器,确切的说,这是一种操作模式:用户提供一组复杂条件,查找出待选的项,通常的实现,是基于一个 TextBox,一个能打开待选项页面或区域的按钮,但选定后再用脚本将用户选择的项填充到 TextBox 里,通常这个 TextBox 还不希望直接修改。(可能说得很复杂,说实例比如日期选择器就是一个典型。)

通常,我们会对 TextBox 加上 ReadOnly="true" 来避免用户的直接输入,这个服务端属性,会在客户端的 HTML input 中输出 readonly="readonly",在 1.1 中,这一切运行得很好,但在 3.5 里,出现了问题,客户端脚本不再可修改 ReadOnly="true"的 TextBox 的值,所以选择器就永远无法选到值。其实,客户端脚本的确改变了 HTML input 的值,只不过一Postback,在服务端又就恢复了旧值。

开始时的解决办法是在页面的pageready事件里,加上

Code


或者直接在服务端用服务器控件的Attribute.Add添加,本质都一样,这样就回避了使用属性 ReadOnly="true" 来禁止输入。到此,问题解决了。

具体来说,问题的根源在System.Web.dll中,拿出Lutz Roeder的宝器,反编译出 TextBox 里到底发生了什么,在LoadPostData方法中我们发现:
if (!this.ReadOnly && !text.Equals(str2, 4))
是的,这就是问题根源,可以看到出于某种原因,微软拒绝了脚本去修改TextBox的Text值。
 

Code

     , NameValueCollection postCollection)
{
    
base.ValidateEvent(postDataKey);
    
string text = this.Text;
    
string str2 = postCollection[postDataKey];
    
if (!this.ReadOnly && !text.Equals(str2, 4))
    {
        
this.Text = str2;
        
return true;
    }
    
return false;
}

 

这样的修复办法真不好,导致一个隐蔽的不兼容问题,让升级过来的系统可能发生意想不到的问题。

直到前几天,我的一位同事告诉我一个更好的办法,这个办法在IE和Firefox下均有效,就是利用 HTML input 的 ContentEditable 属性来控制是否允许输入。

 

Code

 

这也算是个 hack 吧,结论:

在升级ASP.NET 1.1到ASP.NET 3.5时,如果程序中有利用脚本修改属性ReadOnly为true的TextBox时,因替换ReadOnly="True"为ContentEditable="false",这个属性由于不和服务端属性冲突,会被原样输出到客户端,达成同样的效果。

你可能感兴趣的:(readOnly)