Persist user form size and location settings per session

My prior post (Create your own Test Host using XAML to run your unit tests) shows how to create a form and present it to the user. The user can resize and reposition the form, even on a 2nd monitor.

When the user exits the form, we can persist or remember the form size and location, so the next time the user form starts up, it will be positioned/sized as before.

The happens to be a XAML form, but it could be a WinForm for this to work. (The My.Settings feature has been in Visual Studio for many years…)

Because FoxPro has its own database engine, Fox can persist data in a Fox table. The positions and sizes of design time windows, such as the Command Window, Project Window, Database Windows, are persisted in the FoxPro Resource file. The FoxResource class (unzip the xsource.zip file in tools\xsource and look in the EnvMgr folder) can help users persist user forms there too.

To add this feature to your VB project:

Go to Project->Properties->Settings, and add 2 settings:

  • Location, type=System.Drawing.Point, default = 0,0
  • Size, type=System.Drawing.Size, default=1024,768

In the Load or New method:

        If System.Windows.Forms.Screen.AllScreens.Count = 1 AndAlso _

           My.Settings.Location.X > System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width Then

            Me.Left = 0 ' if the saved .X is out of range (multimonitor, remote desktop)

        Else

            Me.Left = My.Settings.Location.X

        End If

        Me.Top = My.Settings.Location.Y

        Me.Width = My.Settings.Size.Width

        Me.Height = My.Settings.Size.Height

        AddHandler Me.Closed, AddressOf OnWindowClosed

 

    Sub OnWindowClosed(ByVal sender As Object, ByVal e As EventArgs)

        My.Settings.Location = New System.Drawing.Point(CInt(Me.Left), CInt(Me.Top))

        My.Settings.Size = New System.Drawing.Size(CInt(Me.Width), CInt(Me.Height))

        My.Settings.Save()

    End Sub

 

 

 

The data is stored in an XML file like:

"C:\Documents and Settings\Calvinh\Local Settings\Application Data\Microsoft\<appname>\1.0.0.0\user.config”

which looks like:

 

<?xml version="1.0" encoding="utf-8"?>

<configuration>

    <userSettings>

        <<appname>.My.MySettings>

            <setting name="Location" serializeAs="String">

                <value>4, 4</value>

            </setting>

            <setting name="Size" serializeAs="String">

                <value>985, 494</value>

        </setting>

        </<appname>.My.MySettings>

    </userSettings>

</configuration>

If you’re feeling brave, you can persist multiple strings using System.Collections.Specialized.StringCollection.

 

I store things like which items are selected and how many asserts are fired per test. Each string will have 3 comma separated items: TestClass,TestName, and AssertCnt

        For Each itm In m_TestMethods

            Dim theitem = itm

            Dim res = From a In My.Settings.AssertsPerTest _

                      Let strs = CStr(a).Split(","c) _

                      Where strs(0) = theitem.TestClass And strs(1) = theitem.TestName _

                      Let Assertcnt = CInt(strs(2))

            If res.Count > 0 Then

                itm.AssertCnt = res.First.Assertcnt

            End If

        Next

 

And just before My.Settings.Save is called, we’ll create the string collection to save.

        Dim ColAssertsPerTest = New Specialized.StringCollection

        For Each itm In From d In TestMethods Where d.AssertCnt > 0

            ColAssertsPerTest.Add(itm.TestClass + "," + itm.TestName + "," + itm.AssertCnt.ToString)

        Next

        My.Settings.AssertsPerTest = ColAssertsPerTest

 

Notice the use of Linq in the For Each expressions.

 

I also use Linq to find the total # of asserts fired:

            Dim nTotalAssertsExpected = Aggregate itm In m_SelectedTests Into Sum(itm.AssertCnt)

 

 

See also: another example of persisting settings: The VB version of the Blog Crawler