oscilatingcretin
oscilatingcretin

Reputation: 10919

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.

Upvotes: 1

Views: 1793

Answers (3)

ShellyFM
ShellyFM

Reputation: 561

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;
    }
}

Upvotes: 0

James Johnson
James Johnson

Reputation: 46047

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.

Upvotes: 1

Jayantha Lal Sirisena
Jayantha Lal Sirisena

Reputation: 21366

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; 

Upvotes: 0

Related Questions