【问题标题】:ASP.NET Server Control - Is shared Viewstate between controls possibleASP.NET 服务器控件 - 控件之间是否可以共享 Viewstate
【发布时间】:2010-10-29 17:20:40
【问题描述】:

如果我有一个带有多个子自定义控件的主“复合自定义服务器控件”,主控件是否可以与子控件共享其视图状态,这些子控件也是自定义复合服务器控件,(所有控件是复合自定义服务器控件)?

再扩展一点,假设我有一个 Person 控件、Address 控件、Phone 控件和 Notes 控制。 AddressPhoneNotes 可以作为独立控件存在,也可以作为 Person 控件的一部分存在。由于每个控件负责自己的视图状态,并在其中存储所需的数据,因此它可以渲染/回发等,最终导致视图状态中存在大量重复,因为 Person 控件存储了所有数据,然后每个子控件再次存储自己的数据。此外,为了使事情更加复杂,Person 控件动态添加子控件,因此可以添加第二个地址/电话号码/注释等,这可能会导致更大的视图状态(高达 1MB) .

如果所有 Address/Phone/etc 控件都是 Person 控件的子控件,我是否可以以某种方式共享公共视图状态数据,所以我在视图状态中没有某些东西的 2/3/4 副本,当它们不是组件时,就照常行事?

我确实有一个解决方案的想法,但它相当讨厌 imo,我可以在其中修改 Person 控件,公开其视图状态或数据,然后在子控件中检查控件层次结构,如果子控件是 Person 的一部分,不要使用它自己的视图状态,使用公开的视图状态。这将需要我重新编写大量现有代码,如果可能的话我宁愿避免这样做。

【问题讨论】:

    标签: asp.net viewstate custom-server-controls


    【解决方案1】:

    我要问的第一个问题是,“您真正需要在 ViewState 中保留多少这些数据?”例如,一个典型的页面请求中是否有足够的信息能够重建其中一些控件中的所有信息?

    我发现 ASP.NET 通常使用 ViewState 的次数远远超过我真正需要的次数,如果您获得 1MB 的视图状态,我怀疑您可能也是如此。我强烈建议阅读this article,以更全面地了解 ViewState 的工作原理、将值保存到 ViewState 的原因以及如何避免在不必要的情况下使用它。例如,您可以通过在 Page_Init 而不是 Page_Load 中做更多的工作来解决大部分问题。

    【讨论】:

    • 我需要保留多少取决于。说了这么多,在阅读了那篇文章之后,感谢链接,我认为问题在于将数据分配给控件的位置,在将控件添加到父控件之后,从而导致不必要的视图状态持久性,而不是先添加数据,然后添加到收藏。我试试这个简单的改变,看看它是否有效
    【解决方案2】:

    您可以通过将 ViewState 作为StateBag 类型传递给任意数量的对象,或者使用返回需要共享的ViewState 的委托函数在任意数量的对象之间“共享”一个 ViewState。然而,这个的用法;应该仅限于非常具体的情况,因为通常控件使用Properties 将其ViewState 数据公开给其他对象(请参阅链接@StriplingWarrior 发布here)。话虽如此,这里有一些示例代码:

    用户控制:SharedState.ascx

    <%@ Control Language="vb" AutoEventWireup="false" CodeBehind="SharedState.ascx.vb" Inherits="TestSite.SharedState" %>
    

    用户控制:SharedState.ascx.vb

    Public Class SharedState
        Inherits System.Web.UI.UserControl
    
        Public Delegate Function GetStateDelegate() As StateBag
    
        Public Const SharedValueKey = "The key used to access the ViewState dictionary"
    
        Public Property GetState() As GetStateDelegate
    
        ' Different ways to get values
        Public Function GetTypedValue(Of TValue)() As TValue
            Return CTypeDynamic(GetValue(), GetType(TValue))
        End Function
    
        Public Function GetValue() As Object
            ' Use the delegate to get the view state from the parent
            Return GetState.Invoke()(SharedValueKey)
        End Function
    
        Public Function GetValue(state As StateBag) As Object
            Return state(SharedValueKey)
        End Function
    
        '  Different ways to set values
        Public Sub SetTypedValue(Of TValue)(value As TValue)
            Me.SetValue(value)
        End Sub
    
        Public Sub SetValue(value As Object)
            GetState.Invoke()(SharedValueKey) = value
        End Sub
    
        Public Sub SetValue(state As StateBag, value As Object)
            state(SharedValueKey) = value
        End Sub
    
        ' Set ViewState value using a key and the delegate
        Public Sub SetStateWithKey(key As String, value As Object)
            GetState.Invoke()(key) = value
        End Sub
    
        ' Get ViewState value using a key and the delegate
        Public Function GetStateWithKey(key As String) As Object
            Return GetState.Invoke()(key)
        End Function
    End Class
    

    页面:SharedStatePage.aspx

    <%@ Page Language="vb" AutoEventWireup="false" CodeBehind="SharedStatePage.aspx.vb" Inherits="TestSite.SharedStatePage" %>
    <%@ Register src="SharedState.ascx" tagname="SharedState" tagprefix="uc1" %>
    
    <uc1:SharedState ID="SharedState1" runat="server" />
    <uc1:SharedState ID="SharedState2" runat="server" />
    

    页面:SharedStatePage.aspx.vb

    Public Class SharedStatePage
        Inherits System.Web.UI.Page
    
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            ' Set up SharedState 1 & 2 to use the delegate '
            SharedState1.GetState = AddressOf GetState
            SharedState2.GetState = AddressOf GetState
    
            ' Set the view state from the page '
            ViewState(SharedState.SharedValueKey) = 23
    
            ' Read the view state from the user controls '
            Dim sharedInt As Integer
            sharedInt = SharedState1.GetTypedValue(Of Integer)()
            sharedInt = SharedState1.GetValue()
            sharedInt = SharedState1.GetValue(ViewState)
            sharedInt = SharedState2.GetValue()
    
            ' Set the view state from one of the user controls '
            SharedState2.SetTypedValue(Of String)("Hello")
            Dim sharedStr As String = ViewState(SharedState.SharedValueKey)
            sharedStr = SharedState1.GetTypedValue(Of String)()
            sharedStr = SharedState2.GetValue()
    
            ' Use a different key to set and get view state data '
            ViewState("MyKey") = New With {.Name = "Some Object", .Value = 46}
            Dim myObj = SharedState1.GetStateWithKey("MyKey")
    
            SharedState2.SetStateWithKey("MyKey", "New Value")
            myObj = ViewState("MyKey")
        End Sub
    
        Private Function GetState() As StateBag
            Return ViewState
        End Function
    End Class
    

    谨慎使用,不要随意使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-12
      • 2020-10-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多