Introduction
Visual WebGui is powerful framework for developing AJAX-based enterprise applications. It is built on top of ASP.NET, and implements a "WinForms"-like programming model to develop enterprise web applications using a rich user interface. It offers a broad range of user controls compatible with the user controls available in WinForms programming model.
Among them there is the Splitter control, which allows to split the workplace in two or more panels, each containing its own controls.
A very useful feature for a splitter is to remember its position at runtime. In this article, I will create a new splitter component, by enhancing the stock Splitter control from Visual Webgui toolbox, to make it remember its location at runtime.
However, one nice feature for splitters would be to allow users to customize the size of the panels, to widen / narrow them to meet various needs, and remember the size when the application is used next time.
So I enhanced the built-in Visual WebGui splitter to implement this feature.
Implementation Details
The thing I faced when I tried to implement this was how to set the splitter position at runtime. After some tests, I noticed the position of the splitter is actually determined not by some properties of the splitter itself, but by the size of the control the splitter is docked on.
To save / restore the splitter position, I use a cookie.
The Persistent Splitter component has design time support, and it has two properties that can be set at design time:
CookieName
- The name of the cookie used to save / load the splitter name DockedControl
- The name of the control the splitter is docked on
The Persistent splitter has two main working private
methods:
SaveSplitterPosition
– This is called from the Resize
event handler for the control the splitter is docked on, and, depending on the dock style of the splitter, it saves in the cookie the value of the width (for vertical splitter) or height (for horizontal splitter) of the docking control. RestoreSplitterPosition
– This is called from the SET
accessor of the HostControlLoaded
property. It tells the splitter that the component that hosts the splitter and related controls (particularly the control the splitter is docked on) was loaded, so their position can be manipulated in code).
The code in SaveSplitterPosition
is straightforward:
private void SaveSplitterPosition()
{
if (m_cookieName != string.Empty)
if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
VWGHelper.SetCookiesParameter
(m_cookieName, m_dockedControl.Width.ToString());
else if (this.Dock == DockStyle.Top || this.Dock == DockStyle.Bottom)
VWGHelper.SetCookiesParameter
(m_cookieName, m_dockedControl.Height.ToString());
else
throw new Exception(string.Format("{0}: Invalid Dock value", this.Name));
}
RestoreSplitterPosition
works similarly. There is only one issue – since in this method we change the size of the docked control, this will fire Resize
event, which will cause the event handler to call SaveSplitterPosition
, which will attempt to save the cookie value again. To prevent this, we unbind from Resize
event when we start the procedure, and bind again when finishing it. The code is shown below:
private void RestoreSplitterPosition()
{
if (m_dockedControl != null && m_cookieName != string.Empty)
{
m_dockedControl.Resize -= new EventHandler(m_dockedControl_Resize);
try
{
string offsetStr = VWGHelper.GetCookiesParameter(m_cookieName);
bool dockValid = false;
if (offsetStr != string.Empty)
{
int offsetInt = Int32.Parse(offsetStr);
if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
{
m_dockedControl.Width = offsetInt;
dockValid = true;
}
else if (this.Dock == DockStyle.Top || this.Dock == DockStyle.Bottom)
{
m_dockedControl.Height = offsetInt;
dockValid = true;
}
if (!dockValid)
throw new Exception(string.Format("{0}:
Invalid Dock value", this.Name));
}
}
catch (Exception ex)
{
throw new Exception
("Error in PersistentSplitter.RestoreSplitterPosition", ex) ;
}
finally
{
m_dockedControl.Resize = new EventHandler(m_dockedControl_Resize);
}
}
}
Using the Code
The PersistentSplitter
functionality is controlled by the HostControlLoaded
property. This is write/only, and is used to notify the splitter when the component the splitter is docked on is available. At that moment, the splitter can restore its position by adjusting the size of its docking component. This should happen in Load
event of the host component (form or user control) by setting the HostControlLoaded
property to true
. This tells the PersistentSplitter
control that all controls on the form were loaded, so it can set the size of left control from the cookie to restore its position (as below):
private void Form1_Load(object sender, EventArgs e)
{
persistentSplitter1.HostControlLoaded = true;
}
You can view a sample application using the PersistentSplitter
component here.
History