【问题标题】:Why can't I update HiddenFields on PostBack?为什么我不能在 PostBack 上更新 HiddenFields?
【发布时间】:2012-05-15 14:43:31
【问题描述】:

这是我的代码:

private string[] MesiSelezionati;

protected void Page_Load(object sender, EventArgs e)
{
    MesiSelezionati = new string[] { "2", "4" };
    UpdateMesi();
}

override protected void OnInit(EventArgs e)
{
    for (int i = 1; i <= 12; i++)
    {
        HtmlGenericControl meseItem = new HtmlGenericControl("a") { InnerHtml = "mese" };
        meseItem.Attributes.Add("href", "javascript:void(0);");

        HiddenField hf = new HiddenField();
        hf.Value = "0";
        hf.ID = "idMese_" + i.ToString();

        meseItem.Controls.Add(hf);

        panelMesi.Controls.Add(meseItem);
    }

    base.OnInit(e);
}

private void UpdateMesi()
{
    foreach (HtmlGenericControl a in panelMesi.Controls.OfType<HtmlGenericControl>())
    {
        HiddenField hf = a.Controls.OfType<HiddenField>().LastOrDefault();
        if (MesiSelezionati.Contains(hf.ID.Split('_').LastOrDefault()))
        {
            hf.Value = "1";
            a.Attributes.Add("class", "box-ricerca-avanzata-item link-box selected");
        }
    }
}

当我调用页面时,一切正常!问题是当我调用同一个页面(所以,回发)时,多亏了 asp:LinkBut​​ton。我在if (MesiSelezionati.Contains(hf.ID.Split('_').LastOrDefault())) 上收到System.NullReferenceException

似乎 2° 和 4° 链接的 HiddenField(对应于MesiSelezionati = new string[] { "2", "4" }; 的位置)为空。为什么?我该如何解决?

编辑:Mark M 的代码

HtmlGenericControl optionBox = new HtmlGenericControl("div");
optionBox.Attributes["class"] = "option-box";

HtmlGenericControl optionBoxItem = new HtmlGenericControl("a") { InnerHtml = "&nbsp;" };
optionBoxItem.Attributes.Add("href", "javascript:void(0);");
optionBoxItem.Attributes.Add("class", "option-box-item");

HtmlGenericControl optionBoxTesto = new HtmlGenericControl("a") { InnerText = Categoria.Categoria };
optionBoxTesto.Attributes.Add("href", "javascript:void(0);");
optionBoxTesto.Attributes.Add("class", "option-box-testo");

HiddenField hf = new HiddenField();
hf.Value = "0";
hf.ID = "categoria_" + Categoria.UniqueID;

optionBox.Controls.Add(optionBoxItem);
optionBox.Controls.Add(optionBoxTesto);
optionBox.Controls.Add(hf);

panelCategorieGuida.Controls.Add(optionBox);

【问题讨论】:

  • 这真的很奇怪!我真的不明白为什么这种行为:O 看起来它丢失了,在回发时,Page_Load 的更新控件,我第一次调用它??????妈的……
  • 是什么让你认为这是更新?您应该检查空引用发生的位置以及原因
  • 嗯.. 没有任何理由让 HiddenFields 在回发时为空。这是我不明白的问题。在回发时,2° 和 4° 链接(第一次调用页面时值已更新的链接)上的 HiddenField 为空。为什么?这就是我需要解决的问题..
  • P.S.他们更新了,是的!当我第一次调用该页面时,我看到的值为“1”,而不是“0”。所以问题实际上是在回发...

标签: c# .net user-controls webforms


【解决方案1】:

您可以在回发时更新隐藏字段,而不是在加载之前。执行 OnInit 时,尚未使用请求和视图状态值填充控件。您的更新将被覆盖。

编辑:我找到了问题的根本原因并在此过程中学到了一些东西。

  1. 您在 OnInit 方法中设置了锚标记 (InnerHtml = "mese") 的 InnerHtml 属性。在后台,这个作业是ViewState["innerhtml"] = "mese"
  2. 您在 ViewState 跟踪开始后将 css 类分配给锚点,因此 ViewState 恢复机制将在回发时应用于此控件。

当您回发带有添加的 css 类的锚标记时,将受制于 HtmlContainerControl.LoadViewState(发生在 InitComplete 和 PreLoad 之间)。如果 LoadViewState 方法检测到 ViewState["innerhtml"] 有一个值,它会清除控件的所有子控件(调用 Controls.Clear())并创建一个 LiteralControl 来包含 innerhtml 值,并将其添加为唯一的子控件。

基本上,这意味着您不能同时设置 InnerHtml 属性并将任何控件添加到 HtmlContainerControl 的后代(如果该控件将受到 ViewState 跟踪)。

修正你的例子;而不是设置 InnerHtml 来添加链接文本,而是创建一个包含所需文本的 LiteralControl 并将其添加到锚点的子控件集合中。

【讨论】:

  • 我认为这不是真的。这很奇怪,因为在另一个上下文中(使用相同的代码,但是“div”而不是“a”)可以工作.. :O
  • 另外,问题是当我进行回发时,而不是当我调用页面时(事实上,在加载时调用页面,它会更新值)。 :O
  • 好吧,因为它只发生在回发时,我怀疑与加载视图状态有关,所以我插入了一些生命周期事件处理程序来缩小问题发生时的范围。一旦我把它放在 InitComplete 和 Load 事件之间,我 97% 确定它是 LoadViewState,所以我下载了 JetBrains 反编译器并从 HtmlGenericControl 向后工作,直到我找到实现 LoadViewState 的类并检查它。 a 受制于它,因为您在视图状态跟踪激活后向其添加了类属性(从加载到 PreRender 处于活动状态)。
  • 但是在我的其他代码上,我有div 而不是a,我也对其应用了class 属性,并且我使用InnerHtml ...但没有任何问题:O
  • 我认为更好的选择是抛出异常,而不是默认为不太可能符合编码器意图的行为。 InnerHTML 和添加子控件是使用子内容填充控件的两种不同且完全独立的方式。如果我设置 InnerHTML 并添加子控件(我想要 InnerHTML 内容首先还是最后?,我是否感到困惑并且只意味着使用这两个选项之一?),则没有自动方法来确定我想要什么,因此应该例外扔掉,IMO。
【解决方案2】:

您的链接按钮是否在某个单独的面板控件中?是否可以使用 AJAX 进行部分回发?很抱歉回答这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-22
    • 2021-07-01
    • 2013-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多