用户控件(ascx)和属性

22

我发现在用户控件内持久化属性值的唯一方法是使用ViewState。

public string Title {
        get { return Convert.ToString(ViewState["Title"]); }
        set { ViewState["Title"] = value; }
    }

虽然我不能说我对此印象深刻,因为用户控件拥有的属性越多,你就会将更多无用的信息存储在ViewState中。是否有更好的方法来保留属性?


3
所有 Web 控件都以相同的方式执行此操作,这就是为什么 ViewState 变得很大的原因... - Robert Koritnik
最终我不得不采取这种方法。它的工作方式相当令人沮丧,但目前它能胜任工作.. :) - Bat_Programmer
6个回答

11

这取决于情况。如果您需要在post-back之后保留属性值,那么您必须使用ViewState或Session。由于这些控件在每个post-back时都会重新创建,否则您就无法维护该状态。


是的,属性值需要通过postback持久化。我在用户控件中有一个按钮,当点击时会引发它的按钮事件(显然),这时我需要检索某些属性值。唉,那我只能膨胀ViewState了! - Jagd
1
如果要在 post-back 之后持久化数据,那么你只能使用 ViewState 或 Session。但这并不适用于 ViewState。ViewState 只在 post-back 之间持久化数据,而不是超出 post-back 范围。 - dariom

8

使用ViewState存储用户控件属性值没有问题。

你的说法“用户控件拥有的属性越多,你就需要在ViewState中存储越多的数据”并不完全正确。虽然可以让ViewState跟踪控件属性的值,但却不一定要将数据存储在__VIEWSTATE隐藏表单字段变量中。

听起来很不可思议,对吧?请参见令人信服的理解ViewState一文,了解关于ViewState的工作原理。

这取决于何时初始化控件属性。只有当控件的StateBag开始跟踪属性值的更改时,ViewState才会存储在隐藏的__VIEWSTATE字段中。这发生在控件的OnInit方法中,即生命周期的早期阶段。但是有一些技巧可以在较早的阶段设置属性值,而不会产生__VIEWSTATE代码膨胀的成本,同时仍然能够享受到所有的好处。

请参阅链接文章。它非常清楚地讨论了所有内容,比我讲得更好 :-)


5
您的问题正是ViewState所用的: 通过跨页面请求来保存控件属性, 所以您的解决方案已经很好了。
您可以将它保存到Session中,但这只是把负担放在服务器上。根据用户数量的不同,这可能会变得非常复杂和麻烦。
此外,请记住,如果使用Session,则需要进行一些维护工作。例如,如果您想在同一页上两次使用自己的用户控件,则需要确保每个控件使用唯一的Session变量。

2

这并不太糟糕 - 这基本上就是内置控件的工作方式,并且通常会导致预期的行为。最好的方法是在您不需要跨后续请求保留这些值时有选择性地禁用ViewState。

您还可以查看ControlState - 它是一个单独的“包”,人们无法禁用它,并且用于GridView之类的东西,其中有些东西无法通过视图状态关闭,因为它会破坏控件。


0

您可以随时重写既定的 SaveViewState/LoadViewState 方法:

public string Title { get; set; }

然后根据需要保存和加载:

protected override object SaveViewState()
{
   // Save State as a cumulative array of objects.
   object baseState = base.SaveViewState();

   object[] allStates = new object[2];
   allStates[1] = _title;
   return allStates;
}

protected override void LoadViewState(object savedState)
{
   if (savedState != null)
   {
      // Load State from the array of objects that was saved during SavedViewState.
      object[] myState = (object[])savedState;
      if (myState[0] != null)
         base.LoadViewState(myState[0]);

      if (myState[1] != null)
         _title = (String)myState[1];
   }
}

-1

你尝试过静态属性吗?还有,记住 HTTP 是无状态的,所以你可以在每个 page_load 上重置你的标题


2
那么当您有两个请求并且它们都想使用用户控件上的不同属性时会发生什么呢? - Wyatt Barnett

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接