I know there are several posts on this topic, but the common answer seems to be, "Make sure all docks are created in the Page_Init" event. As far as I can tell, I've done that. (Using a modified implementation of the Portal example.)
Config is saved to the database as part of the CurrentDockStates property.
I hate to post a mountain of code, but I'm pretty much stuck.
The viewstate error occurs without any real regularity, but once it starts, it doesn't seem to stop until I reset all the docks. It seems to happen most often after deleting a dock.
Many of my docks contain forms, some have timers, their own update panels, etc. I'm guessing that turning off viewstate is not an option...?
Imports System |
Imports System.Collections |
Imports System.Collections.Generic |
Imports System.ComponentModel |
Imports System.Data |
Imports System.Drawing |
Imports System.Web |
Imports System.Web.SessionState |
Imports System.Web.UI |
Imports System.Web.UI.WebControls |
Imports System.Web.UI.HtmlControls |
Imports Telerik.Web.UI |
Imports UserFunctions |
Imports Messages |
Imports Permissions |
Namespace Telerik.Web.Examples.Dock.MyPortal |
Partial Public Class DefaultVB |
Inherits System.Web.UI.Page |
Private Property CurrentDockStates() As List(Of DockState) |
Get |
Dim _currentDockStates As List(Of DockState) = DirectCast(Session("UserPreferences.PortalSession"), List(Of DockState)) |
If [Object].Equals(_currentDockStates, Nothing) Then |
'Make an empty configuration list |
_currentDockStates = New List(Of DockState)() |
'Convert our stored config to the active config |
Dim strLoadedConfig As String = GetUserPreference("PortalConfiguration") |
'If we found nothing, leave the current state empty |
If strLoadedConfig <> "" Then |
Try |
'Use the stored config |
'Convert the stored config to an array, splitting at the *s |
Dim aConfig As Array = Split(strLoadedConfig, "*") |
Dim strConfigItem As String |
Dim dsWorking As DockState |
'Parse through the array, turning the dockstate strings into dockstates |
'Then add the dockstates to the dockstate list |
For Each strConfigItem In aConfig |
'Start a fresh dockstate |
dsWorking = New DockState |
'Parse the string back into dock settings |
dsWorking = DockState.Deserialize(strConfigItem) |
'Add the settings back into the current session |
_currentDockStates.Add(dsWorking) |
Next |
Catch ex As Exception |
'Something was wrong with the data |
'Default back to blank so the page won't crash |
End Try |
'Set the new value into the session variable |
Session("UserPreferences.PortalSession") = _currentDockStates |
Else |
'No config stored; use the default, speficied below |
'Quotes changed to apostrophes for string-friendly input |
Dim strDefaultConfig = "[DEFAULT DOCK CONFIGURATION STRING HERE...]" |
UpdateUserPreference("PortalConfiguration", Replace(strDefaultConfig, "'", """")) |
Try |
'Now, use the newly saved default config to generate the docks |
'The UpdateUserPreference routine would have already stored it in a session |
'Convert the stored config to an array, splitting at the *s |
Dim aConfig As Array = Split(Session("UserPreferences.PortalConfiguration"), "*") |
Dim strConfigItem As String |
Dim dsWorking As DockState |
'Parse through the array, turning the dockstate strings into dockstates |
'Then add the dockstates to the dockstate list |
For Each strConfigItem In aConfig |
'Start a fresh dockstate |
dsWorking = New DockState |
'Parse the string back into dock settings |
dsWorking = DockState.Deserialize(strConfigItem) |
'Add the settings back into the current session |
_currentDockStates.Add(dsWorking) |
Next |
Catch ex As Exception |
'Something was wrong with the data |
'Default back to blank so the page won't crash |
End Try |
'Set the new value into the session variable |
Session("UserPreferences.PortalSession") = _currentDockStates |
End If |
End If |
Return _currentDockStates |
End Get |
Set(ByVal value As List(Of DockState)) |
Session("UserPreferences.PortalSession") = value |
'Session being updated; Update the database too |
'Convert list of dockStates to a delimited string |
'We'll use * since commas are used in the dockStates |
Dim sbListConverter As New System.Text.StringBuilder |
For Each dockState As DockState In value |
sbListConverter.AppendFormat("{0}*", dockState.ToString) |
Next |
Dim strDockConfig As String = sbListConverter.ToString.TrimEnd(Convert.ToChar("*")) |
'Save string to database |
UpdateUserPreference("PortalConfiguration", strDockConfig) |
End Set |
End Property |
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) |
If Not IsPostBack Then |
'Add the dock CSS files to the master page |
Dim newStyleSheet As New HtmlLink() |
newStyleSheet.Href = "skins/LightGreen/Dock.LightGreen.css" |
newStyleSheet.Attributes.Add("type", "text/css") |
newStyleSheet.Attributes.Add("rel", "stylesheet") |
Page.Header.Controls.Add(newStyleSheet) |
End If 'Not Postback |
End Sub |
Public Function GetZones() As ArrayList |
Dim zones As New ArrayList() |
zones.Add(zoneLeft) |
zones.Add(zoneRight) |
Return zones |
End Function |
Protected Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs) |
Dim i As Integer = 0 |
While i < CurrentDockStates.Count |
If CurrentDockStates(i).Closed = False Then |
Dim dock As RadDock = CreateRadDockFromState(CurrentDockStates(i)) |
RadDockLayout1.Controls.Add(dock) |
CreateSaveStateTrigger(dock) |
LoadWidget(dock) |
End If |
System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1) |
End While |
End Sub |
Protected Sub RadDockLayout1_LoadDockLayout(ByVal sender As Object, ByVal e As DockLayoutEventArgs) |
For Each state As DockState In CurrentDockStates |
e.Positions(state.UniqueName) = state.DockZoneID |
e.Indices(state.UniqueName) = state.Index |
Next |
End Sub |
Protected Sub RadDockLayout1_SaveDockLayout(ByVal sender As Object, ByVal e As DockLayoutEventArgs) |
CurrentDockStates = RadDockLayout1.GetRegisteredDocksState() |
End Sub |
Private Function CreateRadDockFromState(ByVal state As DockState) As RadDock |
Dim dock As New RadDock() |
dock.ID = String.Format("RadDock{0}", state.UniqueName) |
dock.ApplyState(state) |
AddHandler dock.Command, AddressOf dock_Command |
dock.Commands.Add(New DockCloseCommand()) |
dock.Commands.Add(New DockExpandCollapseCommand()) |
dock.EnableEmbeddedSkins = False |
dock.Skin = "LightGreen" |
Return dock |
End Function |
Private Function CreateRadDock() As RadDock |
Dim docksCount As Integer = CurrentDockStates.Count |
Dim dock As New RadDock() |
dock.UniqueName = Guid.NewGuid().ToString() |
dock.ID = String.Format("RadDock{0}", dock.UniqueName) |
dock.Title = "" |
dock.Text = "" |
dock.Commands.Add(New DockCloseCommand()) |
dock.Commands.Add(New DockExpandCollapseCommand()) |
dock.EnableEmbeddedSkins = False |
AddHandler dock.Command, AddressOf dock_Command |
Return dock |
End Function |
Sub dock_Command(ByVal sender As Object, ByVal e As DockCommandEventArgs) |
If e.Command.Name = "Close" Then |
ScriptManager.RegisterStartupScript(UpdatePanel1, Me.[GetType](), "RemoveDock", String.Format("function _removeDock() {{" & Chr(13) & "" & Chr(10) & "" & Chr(9) & "Sys.Application.remove_load(_removeDock);" & Chr(13) & "" & Chr(10) & "" & Chr(9) & "$find('{0}').undock();" & Chr(13) & "" & Chr(10) & "" & Chr(9) & "$get('{1}').appendChild($get('{0}'));" & Chr(13) & "" & Chr(10) & "" & Chr(9) & "$find('{0}').doPostBack('DockPositionChanged');" & Chr(13) & "" & Chr(10) & "}};" & Chr(13) & "" & Chr(10) & "Sys.Application.add_load(_removeDock);", (DirectCast(sender, RadDock)).ClientID, UpdatePanel1.ClientID), True) |
End If |
End Sub |
Private Sub CreateSaveStateTrigger(ByVal dock As RadDock) |
dock.AutoPostBack = True |
dock.CommandsAutoPostBack = True |
Dim saveStateTrigger As New AsyncPostBackTrigger() |
saveStateTrigger.ControlID = dock.ID |
saveStateTrigger.EventName = "DockPositionChanged" |
UpdatePanel1.Triggers.Add(saveStateTrigger) |
saveStateTrigger = New AsyncPostBackTrigger() |
saveStateTrigger.ControlID = dock.ID |
saveStateTrigger.EventName = "Command" |
UpdatePanel1.Triggers.Add(saveStateTrigger) |
End Sub |
Private Sub LoadWidget(ByVal dock As RadDock) |
If String.IsNullOrEmpty(dock.Tag) Then |
Return |
End If |
Dim widget As Control = LoadControl(dock.Tag) |
dock.ContentContainer.Controls.Add(widget) |
End Sub |
Protected Sub ButtonAddDock_Click(ByVal sender As Object, ByVal e As EventArgs) |
Dim dock As RadDock = CreateRadDock() |
UpdatePanel1.ContentTemplateContainer.Controls.Add(dock) |
ScriptManager.RegisterStartupScript(dock, Me.[GetType](), "AddDock", String.Format("function _addDock() {{" & Chr(13) & "" & Chr(10) & "" & Chr(9) & "Sys.Application.remove_load(_addDock);" & Chr(13) & "" & Chr(10) & "" & Chr(9) & "$find('{1}').dock($find('{0}'));" & Chr(13) & "" & Chr(10) & "" & Chr(9) & "$find('{0}').doPostBack('DockPositionChanged');" & Chr(13) & "" & Chr(10) & "}};" & Chr(13) & "" & Chr(10) & "Sys.Application.add_load(_addDock);", dock.ClientID, DropDownZone.SelectedValue), True) |
CreateSaveStateTrigger(dock) |
dock.Title = DroptDownWidget.SelectedItem.Text |
dock.Tag = DroptDownWidget.SelectedValue |
'Style the dock, based upon its content |
dock.Skin = "LightGreen" |
LoadWidget(dock) |
End Sub |
End Class |
End Namespace |