views:

17

answers:

1

I know something similar has already been asked, but here's my problem.

In a MDI WinForm I want to save each child window position and state, per application user, that is different by the logged in Windows user. My application has its own users; so I won't use the user settings like my.Settings... etc.

One option is to read/write directly to the database, but I don't like the idea to access the database for something so trivial as the windows positions. The plus is that I could store that information independently by the machine where the user works, wherever she logs in, her preferences will be remembered.

Another option, that I'd like to follow, is to use Xml to store that information in a file locally on the user's computer. The structure could be something like:

<form name="form name">
    <Top>120</Top>
            <Left>100</Left>
            <State>0</State>
    </form>

    <form name="another form">
        <Top>120</Top>
            <Left>120</Left>
            <State>1</State>
    </form>

I'm having a hard time to understand how this could be done; maybe using Linq to Xml? I've found I can write something as simple as

Dim formPos As XElement = _
    <User><%= My.Application.connectedUser.id %>
                <form1>
                    <Top>120</Top>
                    <Left>100</Left>
                    <State>0</State>
                </form1>

                <form2>
                    <Top>120</Top>
                    <Left>100</Left>
                    <State>0</State>
                </form2>
         </User>

But:

1) How to dinamically fill the xml options: I want

<User id="1"> 

and not <User><%= My.Application.connectedUser.id %> that translates to <User>1

2) How to write the XElement when finished building it. Should I use an XmlWriter.Create? Hot to pass it the XElement?

3) What happens when in the Xml file there's already a node with the same name, I want to overwrite the previous user settings if they are already there, but not append to the file, nor rewrite the entire file, of course

Thanks.

A: 

It may be useful to someone else:

Public Shared Sub SaveWindowPosition(ByVal formToSave As Form, ByVal userid As Integer)

        Dim formPosLeft As Integer = formToSave.Location.X
        Dim formPosTop As Integer = formToSave.Location.Y
        Dim formDimWidth As Integer = formToSave.Width
        Dim formDimHeight As Integer = formToSave.Height
        Dim formState As Integer = formToSave.WindowState
        Dim formName As String = formToSave.Name


        '   Apri il file dove memorizzo le posizioni delle varie form
        '
        Dim xdoc As XDocument
        Try
            xdoc = XDocument.Load(FILE_NAME)
        Catch ex As Exception
            '   Non trovato, va creato uno nuovo
            '
            Dim settings As New XmlWriterSettings()
            settings.Indent = True
            Dim writer As XmlWriter = XmlWriter.Create(FILE_NAME, settings)

            writer.WriteStartDocument()
            writer.WriteStartElement("Root")

            writer.WriteEndElement()
            writer.WriteEndDocument()
            writer.Close()

            Try
                xdoc = XDocument.Load(FILE_NAME)
            Catch ex2 As Exception
                '   Nemmeno questa volta è riuscito ad aprire il file, basta
                '
                Exit Sub
            End Try
        End Try

        Dim elementRoot As XElement = xdoc.Element("Root")

        '   Cerca l'utente corrente (per id)
        '
        Dim cercaUtente As IEnumerable(Of XElement) =
            From c In elementRoot.Elements("Utente") Where c.Attribute("id").Value = CStr(userid)
        Select c
        If cercaUtente.Count = 0 Then
            '   Utente non trovato, crealo con tutti gli altri elementi
            '
            Dim xutente As XElement =
                <Utente id=<%= userid %>>
                    <Form name=<%= formName %>>
                        <Position top=<%= formPosTop %> left=<%= formPosLeft %> width=<%= formDimWidth %> height=<%= formDimHeight %> state=<%= formState %>></Position>
                    </Form>
                </Utente>

            elementRoot.Add(xutente)
        Else

            '   Utente trovato, cerca la form 
            '
            Dim cercaForm As IEnumerable(Of XElement) =
                From c In cercaUtente.Elements("Form") Where c.Attribute("name").Value = formName
            Select c

            If cercaForm.Count = 0 Then
                '   Form non trovata, creala
                '
                Dim formPos As XElement = _
                    <Form name=<%= formName %>>
                        <Position top=<%= formPosTop %> left=<%= formPosLeft %> width=<%= formDimWidth %> height=<%= formDimHeight %> state=<%= formState %>></Position>
                    </Form>

                cercaUtente.ElementAt(0).Add(formPos)
            Else
                '   Trovato tutto, sostituisci gli attributi
                '
                Dim position As XElement = cercaForm.ElementAt(0).Element("Position")
                position.ReplaceAttributes(
                    {
                        New XAttribute("top", formPosTop),
                        New XAttribute("left", formPosLeft),
                        New XAttribute("width", formDimWidth),
                        New XAttribute("height", formDimHeight),
                        New XAttribute("state", formState)
                    })

            End If
        End If

        '   Salva il file
        '
        xdoc.Save(FILE_NAME)
    End Sub






Public Shared Sub SetWindowPosition(ByVal formToPosition As Form, ByVal userid As Integer)

        formToPosition.SuspendLayout()

        Dim xdoc As XDocument
        Try
            xdoc = XDocument.Load(FILE_NAME)
        Catch ex As Exception
            '   File non trovato, nulla da fare
            '
            Exit Sub
        End Try

        Dim elementRoot As XElement = xdoc.Element("Root")

        '   Cerca l'utente corrente (per id)
        '
        Dim cercaUtente As IEnumerable(Of XElement) =
            From c In elementRoot.Elements("Utente") Where c.Attribute("id").Value = CStr(userid)
        Select c
        If cercaUtente.Count = 0 Then Exit Sub

        Dim cercaForm As IEnumerable(Of XElement) =
                From c In cercaUtente.Elements("Form") Where c.Attribute("name").Value = formToPosition.Name
            Select c

        If cercaForm.Count = 0 Then Exit Sub

        '   Preleva tutti gli attributi
        '
        Dim position As XElement = cercaForm.ElementAt(0).Element("Position")
        Dim top As Integer = CInt(position.Attribute("top"))
        Dim left As Integer = CInt(position.Attribute("left"))
        Dim width As Integer = CInt(position.Attribute("width"))
        Dim height As Integer = CInt(position.Attribute("height"))
        Dim state As FormWindowState = CType([Enum].Parse(GetType(FormWindowState), CStr(position.Attribute("state"))), FormWindowState)

        '   Imposta posizione, dimensione e stato, ma solo se lo stato è normale, altrimenti ignora i valori 
        '
        formToPosition.WindowState = state

        If state = FormWindowState.Normal Then
            formToPosition.Location = New Point(left, top)
            formToPosition.Width = width
            formToPosition.Height = height
            formToPosition.StartPosition = FormStartPosition.Manual
        End If

        '   TODO: controllare che posizione e dimensioni siano NORMALI cioè che la form non vada a finire fuori dallo schermo 

        formToPosition.ResumeLayout(False)
    End Sub
vulkanino