Tuesday, June 12, 2007

In my last article, I have described a "feature" of some of the properties of ASP.NET controls: recursive properties. It is obvious why it is important to know about it, but how does it impact the development?

Imagine that you need the following functionality: Page with on it controls and among them, there is a panel containing buttons such as Save, Cancel etc. This panel is inside some kind of container control - like div tag. The goal is to detect if there is at least one visible button inside the container. If so, render the container, otherwise, containing div should not be rendered at all.

<div runat="server" id="ActionPanel">
    <asp:Button runat="server" ID="Save" />
    <asp:Button runat="server" ID="Cancel" />
</div>

The code to accomplish this is "easy". Get the reference to the div control (which was made to runat="server"). Iterate over its child controls and for each control, that was a Button, check its Visible property. If at least one of the property returns true, the div should also be visible. Sample code to achieve this:

protected override void OnPreRender(EventArgs e)
{
    ActionPanel.Visible = GetActionPanelVisibleStatus();
}
private bool GetActionPanelVisibleStatus()
{
    foreach (Control control in ActionPanel.Controls)
    {
        if ((control is Button) && (control.Visible))
        {
            return true;
        }
    }
    return false;
}

I'm using a loop over all child controls to make it more generic.

The only problem is that above implementation does not work in some cases. The problematic situation only occurs if the div's Visible property is set to false. Once invisible, it stays that way with no way of going back to visible state! Why is that? Of course it is because of the recursive nature of Visible property. With this in mind it is easy to fix the problem by setting Visible property of the container control to true, before processing it's child controls:

protected override void OnPreRender(EventArgs e)
{
    ActionPanel.Visible = true;
    ActionPanel.Visible = GetActionPanelVisibleStatus();
} 

Makes sense?

Gathering it all up, it is now easy to build a self-hiding ASP.NET control (or UserControl). Just remember about recursion!

kick it on DotNetKicks.com