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

Hei*_*nzi 3 asp.net viewstate datagrid textbox

示例 1:

<asp:Panel Visible="false" runat="server">
    <asp:TextBox ID="textbox" runat="server" />
</asp:Panel>
Run Code Online (Sandbox Code Playgroud)

在这里,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>
Run Code Online (Sandbox Code Playgroud)

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


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

(当然,在第二种情况下,文本框位于模板内,但我不是在模板定义中查询抽象文本框,而是在第 0 行查询特定的具体文本框。)

背景: TextBox 是一个智能控件:它仅在不可见时才将其 Text 属性保存在 ViewState 中。这是有道理的:如果 TextBox 可见,它将呈现为 HTML<input>控件,并且其当前Text值在回发时提交 - 无需通过 ViewState 再次提交。当然,如果 TextBox 不可见,则不会呈现它,因此,对Text属性所做的任何更改都将丢失。

现在,示例 2 给我们带来了一些麻烦。textbox认为它正在被渲染(根据 IL spy,它在 中检查自己的Visible属性TextBox.SaveTextViewState),因此它不使用 ViewState,并且textbox.Text在代码中完成的所有更改都将丢失。我现在想知道这是否是错误。


相关问题: 如何在 Asp.Net 中获取 Visible 属性的设置/实际值。


编辑:我已经就此创建了 Microsoft Connect 错误报告:

rsb*_*rro 5

TextBox并且Panel都继承自WebControl,继承自ControlControlVisible属性具有以下定义:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

由于Visible没有直接在 上实现TextBoxfalse如果Visible父级的属性为 false(在运行时并且如果指定了父级),它将始终返回。因此,为了回答标题中提出的问题,该Visible属性不会false在任何时间点自动设置为,它只是在访问时进行评估。在GridViewwhereTextBox.Visible返回的情况下true,按理说 的父控件TextBox不是TemplateColumn,或者至少父控件没有将其Visible属性设置为 false。

编辑
因此,使用您的示例格中的问题,如果你走的控制链,你会看到,所有的父控件为TextBoxVisible。我使用了下面的代码,这是输出:

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)
Run Code Online (Sandbox Code Playgroud)

代码:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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