服务器控件和视图状态

时间:2008-12-08 16:35:16

标签: asp.net webforms servercontrols

好的时候表明我完全缺乏对所有网页表单的了解,但是这里有。我正在扩展Panel控件和OnPreRender在其中添加一些额外的控件(为简单起见,我们只说一个文本框)。从这里我只是让Panels Render方法做它的事情。

我遇到的问题是,显然每次重新呈现此控件时,只需在面板中使用OnPreRender方法编码的值再次使用相同的TextBox。现在我实际上并不想每次重新填充面板,

我希望在第一次加载时将文本框控件保留在那里,并从控件/视图状态缓存中重新加载它们。在这种情况下,我只是在面板中粘贴一个文本框的示例,如果文本框的值发生更改并发生回发,我希望该值保持更改的值。

我知道真正基本的webforms,但我从来没有在我的时间创建自定义控件。非常感谢。

克里斯。

4 个答案:

答案 0 :(得分:3)

你需要(重新)在OnInit中创建子控件(文本框) - 以便在调用LoadViewState和ProcessPostBackData时它就在那里。

有关详细信息,请参阅server control lifecycle

答案 1 :(得分:1)

ASP.NET中的动态控件非常棘手,尤其是如果您不熟悉webforms和页面生命周期。如果可以避免动态控制,请执行此操作。使用controlName.Visible = false和其他技巧。

如果您必须阅读this article。经验法则,在页面生命周期的早期添加控件,稍后在页面生命周期中引用它们。 PreRender几乎是最终的,是一个不常见的添加和使用控件的地方。

答案 2 :(得分:1)

不确定这是否适用于所有版本的.Net,(我认为是2.0或更高版本)但是有一个名为CreateChildControls的方法并不完全是生命周期的一部分,它基本上在调用EnsureChildControls方法时调用。默认情况下,如果它不是回发,则在PreRender之前调用它。所以基本上你的代码看起来像这样:

public class SomeControl : WebControl, INamingContainer
{
  private TextBox someTextBox;

  protected override void CreateChildControls()
  {
    base.CreateChildControls();

    someTextBox= new TextBox();
    someTextBox.ID = "tbxMain";

    Controls.Add(textboxToCheck);
  }
}

现在除非你调用EnsureChildControls,否则你不能100%确定控件是否存在,之后控件的公共属性被ViewState加载填充。这是什么意思?那么从以前获取代码并为CssClass添加一个属性:

public class SomeControl : WebControl, INamingContainer
{
  private TextBox someTextBox;

  protected override void CreateChildControls()
  {
    base.CreateChildControls();

    someTextBox= new TextBox();
    someTextBox.ID = "tbxMain";

    Controls.Add(textboxToCheck);
  }

  public String CssClass { get; set; }
}

在CreateChildControls中你不会想要这个:

someTextBox.CssClass = CssClass;

由于无法确定控件是否存在。有几种方法可以解决这个问题:

public String CssClass    {      得到      {        EnsureChildControls();        return someTextbox.CssClass;      }

 set
 { 
   EnsureChildControls();
   someTextbox.CssClass = value;
 }

在这个例子中,我调用EnsureChildControls(假设您在CreateChildControls方法的文本框中设置CssValue)并设置或从文本框中获取。

另一种方法是在OnPreRender方法中放置任何依赖于控件的公共属性的东西:

protected override void OnPreRender(EventArgs e)
{
  someTextbox.CssClass = CssClass;
}

因此避免在ViewState加载期间担心已填充的属性。

一个注意事项:

使用INamingContainer非常重要。基本上所做的就是通过将父名称(可能更多)应用于id来确保父控件上的控件具有页面上唯一的ID。基本上,如果父ID是Parent,并且子控件ID是Child,则ID可能显示为Parent_Child。这将解决ViewState没有正确填充属性或根本不填充属性的问题。

答案 3 :(得分:0)

如果您需要viewstate服务,则需要在代码内部管理viewstate信息的恢复。

这里的一个很好的例子是微软的View State example。代码示例中引用了一些其他项,但它应该让您沿着正确的路径前进。