问题描述
在 ASP.NET 4 的 WebForm 应用程序中,将 ListBox 服务器控件的 Enabled 属性设置为 false 后,并没有禁用该控件。
测试程序
测试程序的 WebForm 页面文件 TestForm.aspx:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TestForm.aspx.cs" Inherits="WebAppTester.TestForm" %> <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> < html xmlns="http://www.w3.org/1999/xhtml"> < head runat="server"> < title >测试页</ title > < link href="Main.css" rel="stylesheet" type="text/css" /> </ head > < body > < form id="form1" runat="server"> < div > < asp:ListBox ID="lstTest" Rows="4" runat="server" /> < asp:Button ID="btnDisable" Text="禁用" OnClick="Button_Click" runat="server" /> < asp:Button ID="btnEanble" Text="启用" OnClick="Button_Click" Enabled="false" runat="server" /> </ div > </ form > </ body > </ html > |
以及相应的代码隐藏文件 TestForm.aspx.cs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | using System; using System.Web.UI; using System.Web.UI.WebControls; using Skyiv.Common; namespace WebAppTester { public partial class TestForm : PageEx { protected void Page_Load( object sender, EventArgs e) { if (!IsPostBack) { lstTest.DataSource = Enum.GetNames( typeof (DateTimeKind)); lstTest.SelectedIndex = 1; lstTest.DataBind(); } } protected void Button_Click( object sender, EventArgs e) { Switch(((Button)sender) == btnEanble); } void Switch( bool isEnable) { btnDisable.Enabled = isEnable; btnEanble.Enabled = !isEnable; if (isEnable) lstTest.Enable(); else lstTest.Disable(); } } } |
下面是 PageEx.cs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | using System; using System.Web.UI; using System.Web.UI.WebControls; namespace WebAppTester { public abstract class PageEx : Page { protected override void OnLoadComplete(EventArgs e) { base .OnLoadComplete(e); RunDisabledListSelectedListItem( this ); } void RunDisabledListSelectedListItem(Control top) { foreach (Control ctl in top.Controls) { var lst = ctl as ListControl; if (lst != null && !lst.Enabled) foreach (ListItem item in lst.Items) if (item.Selected) item.Attributes.Add( "class" , WebControl.DisabledCssClass); RunDisabledListSelectedListItem(ctl); } } } } |
上述 RunDisabledListSelectedListItem 方法是为了配合 Main.css,用以补救 IE 8、IE 9 和 Chrome 浏览器的 bug 的。还有定义扩展方法的 WebControlExtensions.cs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | using System.Web.UI.WebControls; namespace Skyiv.Common { public static class WebControlExtensions { static readonly string tagDisabled = "disabled" ; public static void Enable( this WebControl ctl) { ctl.Enabled = true ; ctl.Attributes.Remove(tagDisabled); } public static void Disable( this WebControl ctl) { ctl.Enabled = false ; ctl.Attributes.Add(tagDisabled, tagDisabled); } } } |
上述 Disable 扩展方法就是用来补救 ListBox 服务器控件无法被禁用的。
最后是样式表 Main.css:
1 2 3 4 5 | option.aspNetDisabled { color : White; background-color : #00FFFF ; } |
运行结果
上述测试程序的运行结果如下所示:
点击“禁用”按钮后:
相应的的 HTML 页面源代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> < html xmlns="http://www.w3.org/1999/xhtml"> < head >< title >测试页</ title > < link href="Main.css" rel="stylesheet" type="text/css" /> </ head > < body > < form method="post" action="TestForm.aspx" id="form1"> < div class="aspNetHidden">< input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/w ... YP" /></ div > < div class="aspNetHidden">< input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/w ... tA" /></ div > < div > < select size="4" name="lstTest" id="lstTest" class="aspNetDisabled" disabled="disabled"> < option value="Unspecified">Unspecified</ option > < option selected="selected" value="Utc" class="aspNetDisabled">Utc</ option > < option value="Local">Local</ option > </ select > < input type="submit" name="btnDisable" value="禁用" id="btnDisable" disabled="disabled" class="aspNetDisabled" /> < input type="submit" name="btnEanble" value="启用" id="btnEanble" /> </ div > </ form > </ body > </ html > |
可以看出,上述 HTML 源代码中第 11 行的 select HTML 元素已经添加了 disabled 属性,第 13 行的的 option 子元素也添加了 class 属性,以便对应 Main.css 中相应的样式,补救在 IE 8、IE9 和 Chrome 19.0 浏览器中不能正确显示的 bug。
MSDN 中的说法
在 MSDN 的 ASP.NET 4 和 Visual Web Developer 中的新增功能 中提到:
用于可禁用控件的 CSS 在 ASP.NET 3.5 中,禁用某个控件时(请参见 WebControl.Enabled),会将一个 disabled 特性添加到呈现的 HTML 元素中。 例如,下面的标记将创建一个已禁用的 Label 控件: <asp:Label id="Label1" runat="server" Text="Test" Enabled="false" /> 在 ASP.NET 3.5 中,原有控件设置将生成以下 HTML: <span id="Label1">Test</span> 在 HTML 4.01 中,针对 span 元素将 disabled 特性视为无效。 它仅对 input 元素有效,因为它指定这些元素无法访问。 对于仅供显示的元素(如 span),浏览器通常支持呈现禁用的外观,但根据辅助功能标准,依赖于这种非标准行为的网页并不可靠。 对于仅供显示的元素,应使用 CSS 指明已禁用的可视外观。 因此在默认情况下,ASP.NET 4 将针对上面显示的控件设置生成以下 HTML: <span id="Label1" class="aspNetDisabled">Test</span> 通过设置 DisabledCssClass 属性,可以更改控件禁用时默认呈现的 class 特性的值。
实际上,在 ASP.NET 4 中,如果将 WebControl 的 Enabled 属性设置为 false,ListBox 服务器控件对应的 select HTML 元素的确没有被添加 disabled 属性。而 Button 服务器控件对应的 input HTML 元素还是被添加 disabled 属性。照理说,select HTML 元素也不能说是仅供显示的元素吧。
使用 ASP.NET 3.5 兼容模式
如果使用 ASP.NET 3.5 兼容模式来呈现页面,也可以解决问题,需要在 web.config 文件中作如下设置:
1 2 3 4 5 6 | <? xml version="1.0" encoding="utf-8"?> < configuration > < system.web > < pages controlRenderingCompatibilityVersion="3.5" /> </ system.web > </ configuration > |
但是这就无法利用 ASP.NET 4 的优点了,不推荐使用。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述