ASP.NET 3.5: How to keep child controls from beind disabled when parent control is disabled?
Take this simple example for example:
<asp:Panel ID="pnlTest" runat="server">
<asp:TextBox ID="txPanelText" Text="Text" runat="server" />
</asp:Panel>
Now, in the codebehind, do this:
pnlTest.Enabled = false;
txPanelText.Enabled = true;
Why does disabling the panel also disable the textbox within it? Furthermore, why does explicitly enabling the textbox have no effect?
This obviously has something to do with the ASP.NET framework. Is there any way I开发者_运维知识库 can avoid this?
NOTE: This is not the actual code I am using in my application. It's just an example to show how disabling a control also recursively disables all child controls within it.
That is by design, and to achieve the effect that you're looking for you'll need to use a different approach. I would suggest recursively iterating through the child controls and using some logic to determine which controls get disabled and which don't.
you can do this in client side using javascript.
var controls = document.getElementById("<%=pnlTest.ClientID%>").getElementsByTagName("input");
for (var i = 0; i < controls.length; i++)
controls[i].disabled = true;
This is because the controls have an additional internal property called IsEnabled that is returned as False if the control or any of the controls in the parent tree have Enabled set to False. During rendering, the TextBox adds the disabled attribute if this IsEnabled property is False.
You could create your own custom controls by inheriting from the Panel and TextBox controls and add in your own properties and logic. Something like what I have below should work.
Also, I wouldn't recommend rendering the disabled attribute on the Panel, which renders as a div. The disabled attribute is not a standard html attribute for a div, and the browsers render the contents inconsistently. For example, IE 9 dims an inner text box (if the text box does not have its own disabled attribute) BUT you can still modify the text box value. Firefox ignores the tag and renders the text box as normal.
public class TextBox : System.Web.UI.WebControls.TextBox, IDisabled
{
public System.Nullable<bool> Disabled
{
get { return (System.Nullable<bool>)ViewState["Disabled"]; }
set { ViewState["Disabled"] = value; }
}
public override bool Enabled
{
get
{
if (this.Disabled.HasValue)
{
return !this.Disabled.Value;
}
else
{
return true;
}
}
set { this.Disabled = !value; }
}
protected override void AddAttributesToRender(System.Web.UI.HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
if (Utilities.RenderDisabled(this))
{
writer.AddAttribute(System.Web.UI.HtmlTextWriterAttribute.Disabled, "disabled");
}
}
}
public class Panel : System.Web.UI.WebControls.Panel, IDisabled
{
public System.Nullable<bool> Disabled
{
get { return (System.Nullable<bool>)ViewState["Disabled"]; }
set { ViewState["Disabled"] = value; }
}
public override bool Enabled
{
get { return true; }
set { this.Disabled = !value; }
}
}
public interface IDisabled
{
System.Nullable<bool> Disabled { get; set; }
bool Enabled { get; set; }
}
public sealed class Utilities
{
public static bool RenderDisabled(IDisabled control)
{
return (control.Disabled.HasValue && control.Disabled.Value) || (!control.Disabled.HasValue && IsParentDisabled(control));
}
public static bool IsParentDisabled(IDisabled control)
{
System.Web.UI.Control current = ((System.Web.UI.Control)control).Parent;
IDisabled currentDisabled = default(IDisabled);
while (current != null)
{
currentDisabled = current as IDisabled;
if (currentDisabled != null && currentDisabled.Disabled.HasValue)
{
return currentDisabled.Disabled.Value;
}
current = current.Parent;
}
return false;
}
}
精彩评论