asp.net:子控件的Visible属性何时自动设置?

时间:2011-07-13 16:27:57

标签: asp.net datagrid textbox viewstate

示例1:

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

此处,textbox.Visible在代码中返回false(即使TextBox.Visible未明确设置;它似乎从其不可见的父级“继承”该属性。)

示例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>

此处,((TextBox)grid.Items[0].FindControl("textbox")).Visible返回true(假设DataGrid至少有一行)。


问题:这种设计不一致吗?在这两种情况下,TextBox都不会呈现,因为某些父元素是不可见的。

(当然,在第二种情况下,文本框位于模板中,但我没有在模板定义中查询抽象TextBox,我正在查询第0行中具体的具体TextBox。)

背景: TextBox是一个智能控件:It only saves its Text property in the ViewState if it's invisible.这是有道理的:如果TextBox可见,它将呈现为HTML <input>控件及其当前{{1值在回发时提交 - 无需通过ViewState再次提交。当然,如果TextBox不可见,则不会呈现它,因此,对Text属性的任何更改都将丢失。

现在,示例2给我们带来了一些麻烦。 Text认为它正在呈现(根据IL间谍,它在textbox中检查自己的Visible属性),因此它不使用ViewState和{{1}的所有更改代码中的完成丢失了。我现在想知道这是不是错误。


相关问题: How to get the set/real value of the Visible property in Asp.Net.


编辑:我已就此创建了Microsoft Connect Bug报告:

1 个答案:

答案 0 :(得分:4)

TextBoxPanel都继承自WebControl,继承自ControlControl具有Visible属性的以下定义:

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

由于Visible未直接在TextBox上实现,因此如果父项的false属性为false(在运行时且如果有),它将始终返回Visible父指定)。因此,为了回答标题中提到的问题,Visible属性在任何时间点都不会自动设置为false,只是在访问时才进行评估。如果GridView TextBox.Visible返回true,则TextBox的父控件不是TemplateColumn,或者至少是父项的Visible属性设置为false。

修改
因此,在问题中使用示例网格,如果您向上走控制链,您将看到TextBox的所有父控件都是Visible。我使用下面的代码,这是输出:

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)

代码:

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

在我看来,DataGridVisisble属性正在按预期工作。