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

发布于 2024-11-24 07:51:14 字数 2041 浏览 5 评论 0原文

示例 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 至少有一行)。


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

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

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

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


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


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

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 not 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:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

白芷 2024-12-01 07:51:14

TextBoxPanel都继承自WebControl,而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);
    }
}

由于 Visible 不是直接在 TextBox 上实现的,因此它始终会如果父级的 Visible 属性为 false(在运行时且指定了父级),则返回 false。因此,为了回答标题中提出的问题,Visible 属性在任何时间点都不会自动设置为 false,它只是在访问时进行评估。在 GridViewTextBox.Visible 返回 true 的情况下,按理说 TextBox 的父控件code> 不是 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 属性按预期工作。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文