开发者

asp.net: When is the Visible property of child controls automatically set?

Example 1:

<asp:Panel Visible="false" runat="server">
    <asp:TextBox ID="textbox" runat="server" />
</asp:Panel>

Here, textbox.Visible returns false in code (even though TextBox.Visible was n开发者_StackOverflowot set explicitly; it seem to "inherit" the property from its invisible parent).

Example 2:

<asp:DataGrid ID="grid" runat="server" AutoGenerateColumns="false">
    <Columns>
        <asp:TemplateColumn Visible="False">
            <ItemTemplate>
                <asp:TextBox ID="textbox" runat="server" />
            </ItemTemplate>
        </asp:TemplateColumn>
    </Columns>
    ...
</asp:DataGrid>

Here, ((TextBox)grid.Items[0].FindControl("textbox")).Visible returns true (under the assumption that the DataGrid has at least one row).


Question: Is this inconsistent behaviour by design? In both cases, the TextBox is not rendered because some parent element is invisible.

(Granted, in the second case the textbox is inside a template, but I'm not querying an abstract TextBox in the template definition, I'm querying the specific, concrete TextBox in row number 0.)

Background: TextBox is a smart control: It only saves its Text property in the ViewState if it's invisible. That makes sense: If the TextBox is visible, it's rendered as a HTML <input> control and its current Text value is submitted on a postback - no need to submit it again via the ViewState. Of course, if the TextBox is invisible, it is not rendered, and, thus, any changes to the Text property would be lost.

Now, Example 2 is giving us some trouble. textbox thinks that it's being rendered (according to IL spy, it checks its own Visible property in TextBox.SaveTextViewState), so it doesn't use the ViewState and all changes to textbox.Text done in code are lost. I'm now wondering whether this is bug or not.


Related question: How to get the set/real value of the Visible property in Asp.Net.


EDIT: I've created a Microsoft Connect Bug Report on this:

  • Webforms: Control.Visible does not recognize that the control is within an invisible DataGrid column


TextBox and Panel both inherit from WebControl, which inherits from Control. Control has the following definition for the Visible property:

public virtual bool Visible
{
    get
    {
        return !this.flags[16] &&
               (this._parent == null || this.DesignMode || this._parent.Visible);
    }
    set
    {
        if (this.flags[2])
        {
            bool flag = !this.flags[16];
            if (flag != value)
            {
                this.flags.Set(32);
            }
        }
        if (!value)
        {
            this.flags.Set(16);
            return;
        }
        this.flags.Clear(16);
    }
}

Since Visible is not implemented directly on TextBox, it will always return false if the Visible property of the parent is false (at runtime and if there is a parent specified). So to answer the question asked in the title, the Visible property is not automatically set to false at any point in time, it's just evaluated when it is accessed. In the case of the GridView where TextBox.Visible returns true, it stands to reason that the parent control of the TextBox is not the TemplateColumn, or at least the parent does not have its Visible property set to false.

EDIT
So, using your example grid in the question, if you walk the chain of controls up, you'll see that all of the parent controls for the TextBox are Visible. I used the code below, and here's the output:

TextBox (ClientID = grid_textbox_0, Visible = True)
TableCell (ClientID = grid_ctl00_0, Visible = True)
DataGridItem (ClientID = grid, Visible = True)
ChildTable (ClientID = grid_ctl00, Visible = True)
DataGrid (ClientID = grid, Visible = True)
HtmlForm (ClientID = form1, Visible = True)

Code:

protected void btnSubmit_Click(object sender, EventArgs e)
{
    var control = grid.Items[0].FindControl("textbox");
    while(control != this && control != null)
    {
        Response.Write(string.Format("{0} (ClientID = {1}, Visible = {2})",
            control.GetType().Name, control.ClientID, control.Visible));
        Response.Write("<br />");
        control = control.Parent;
    }
}

It seems to me that the DataGrid and the Visisble properties are working as expected.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜