Avatar billede madssch Nybegynder
09. marts 2006 - 10:32 Der er 18 kommentarer og
1 løsning

Globale variabler

Hej Eksperter!

Jeg har i mit system en Sub, som læser nogle indstillinger, som er gemt i et XML dokument. Indholdet af XML dokumentet gemmer jeg i nogen vaiabler.

Jeg vil gerne kunne bruge disse variabler rundt omkring i mine andre subs - hvordan får jeg det strikket sammen?
Avatar billede clausc Nybegynder
09. marts 2006 - 10:57 #1
Jeg vil anbefale en Singleton klasse. Kig evt på http://www.dotnetforum.dk/blogs/pally/archive/2004/03/28/65514.aspx

static i C# = shared i VB, derudover burde det være ligetil at oversætte.
Avatar billede madssch Nybegynder
09. marts 2006 - 11:24 #2
Ud over det med Sidse Babett, forstod jeg desværre ikke ret meget af det.  :)

Jeg er helt ny i VB.NET, så måske du kunne forklare lidt - eller endnu bedre komme med et konkret eksempel?

Dette er min kode som skal eksekveres ved opstart, men som også skal kunne kaldes løbende:

    Public Sub LoadSettings()

        Dim SystemReader As New System.IO.StreamReader("Settings.xml")
        Dim XMLTextReader As New System.Xml.XmlTextReader(SystemReader)
        Dim SettingsDoc As New System.Xml.XmlDocument

        SettingsDoc.Load(XMLTextReader)

        Dim SettingItems As System.Xml.XmlNodeList = SettingsDoc.SelectNodes("settings/items")

        Dim SoundAlert As System.Xml.XmlNode = SettingItems.Item(0).SelectSingleNode("soundalert")
        Dim PopupAlert As System.Xml.XmlNode = SettingItems.Item(0).SelectSingleNode("popupalert")

        Dim SoundAlertActive As String = SoundAlert.InnerText
        Dim PopupAlertActive As String = PopupAlert.InnerText

        XMLTextReader.Close()
        SystemReader.Close()

    End Sub
Avatar billede clausc Nybegynder
09. marts 2006 - 12:05 #3
Noget i stil med (find selv et bedre klassenavn end Singleton):

Public Class Singleton
  Private Shared FInstance As Singleton = Nothing

  Private FSoundAlert As String
  // osv med andre data du vil eksponere

  Private Sub New()
    // Din kode her hvor du indlæser data
    FSoundAlert = ...
  End Sub

  Public Sub Save()
    // Noget kode der gemmer settings
  End Sub

  Public Shared ReadOnly Property Instance() As Singleton
    Get
      If (FInstance Is Nothing) Then
        FInstance = New Singleton()
      End If

      Return FInstance
    End Get
  End Property

  Public Property SoundAlert() As String
    Get
      FSoundAlert
    End Get
  End Property

  // osv for andre properties

End Class

Ok. Nu er det smarte så at du alle andre steder i din kode altid får fat i én og samme instans af Singleton-klassen. Dermed er de properties der er på Singleton klassen reelt globale data.

  ...
  aVar = Singleton.Instance.SoundAlert
  ...

  og

  ...
  Singleton.Instance.SoundAlert = "new setting"
  ...
Avatar billede madssch Nybegynder
09. marts 2006 - 12:34 #4
Vil det også være globale data flere forms imellem?

Jeg skal nemlig bruge variablerne i 2 forskellige forms.

Er det noget med, at jeg kan gemme ovenstående class i en form, og så inkludere denne form i de andre forms ved hjælp af "Inherit" eller sådan noget?

Det skal måske lige siges, at jeg bruger Visual Studio .NET 2005 Express...
Avatar billede clausc Nybegynder
09. marts 2006 - 12:39 #5
Ja, data er globale i og med at alle forme og andre klasser får fat i samme instans af klassen.

Lad klassen være selvstændig og bare kald Singleton.Instance.DinProperty fra de forme, der skal læse/skrive data.
Avatar billede madssch Nybegynder
09. marts 2006 - 12:45 #6
Som sagt er jeg helt ny i dette, så jeg skal lige have bekræftet at, at jeg skal placere denne klasse i en ny form, eller..?

Indsætter jeg klassen i MainForm.vb (hovedform) - bliver den så stadig tilgængelig for andre forms?
Avatar billede clausc Nybegynder
09. marts 2006 - 12:48 #7
Du skal tilføje en ny klasse til dit projekt. Nu har jeg ikke Express ved hånden; men det må være noget a la:

Project -> Add New -> VB Class
Avatar billede madssch Nybegynder
09. marts 2006 - 12:54 #8
Jeps, det har jeg gjort.

Har prøvet at tilpasse koden du sendte, men får problemer ved de 2 "Public Property" områder:

Public Class SystemSettings

    Private Shared FInstance As SystemSettings = Nothing

    Private SoundAlertActive As String
    Private PopupAlertActive As String

    Private Sub LoadSettings()

        Dim SystemReader As New System.IO.StreamReader("Settings.xml")
        Dim XMLTextReader As New System.Xml.XmlTextReader(SystemReader)
        Dim SettingsDoc As New System.Xml.XmlDocument

        SettingsDoc.Load(XMLTextReader)

        Dim SettingItems As System.Xml.XmlNodeList = SettingsDoc.SelectNodes("settings/items")

        Dim SoundAlert As System.Xml.XmlNode = SettingItems.Item(0).SelectSingleNode("soundalert")
        Dim PopupAlert As System.Xml.XmlNode = SettingItems.Item(0).SelectSingleNode("popupalert")

        SoundAlertActive = SoundAlert.InnerText
        PopupAlertActive = PopupAlert.InnerText

        XMLTextReader.Close()
        SystemReader.Close()

    End Sub

    Public Sub SaveSettings()
        ' Noget kode der gemmer settings
    End Sub

    Public Shared ReadOnly Property Instance() As SystemSettings

        Get

            If (FInstance Is Nothing) Then
                FInstance = New SystemSettings()
            End If

            Return FInstance

        End Get

    End Property

    Public Property SoundAlertActive() As String

        Get
            SoundAlertActive()
        End Get

    End Property

    Public Property PopupAlertActive() As String

        Get
            PopupAlertActive()
        End Get

    End Property

End Class

Kan du tyde den?
Avatar billede clausc Nybegynder
09. marts 2006 - 13:04 #9
Jep. Du har kaldt dine interne fields det samme som property'erne selv:
Private SoundAlertActive As String
Private PopupAlertActive As String

Kald i stedet dine interne fields for f.eks.
Private FSoundAlertActive As String
Private FPopupAlertActive As String

Og så skal der stå (skrivefejl fra min side, sorry):
Public Property SoundAlertActive() As String
  Get
    Return FSoundAlertActive
  End Get

  Set
    FSoundAlertActive = Value
  End Set
End Property
Avatar billede madssch Nybegynder
09. marts 2006 - 13:15 #10
Nu begynder det at ligene noget. Kan debugge uden problemer.

Og hvordan er det så du siger, at jeg kalder mine variabler?
Avatar billede clausc Nybegynder
09. marts 2006 - 13:25 #11
Lad os sige du vil aflæse en af dine settings i en form; det vil du typisk gøre i Form_Load(). Så skal du skrive noget i stil med:

Sub Form_Load(...)
  ...
  Dim alertSound As String
  alertSound = SystemSettings.Instance.SoundAlertActive
  ...
End Sub

Hvis du i en anden form f.eks vil opdatere værdien bliver det i stil med:

Sub UpdateAlertSound_OnClick(...)
  ...
  SystemSettings.Instance.SoundAlertActive = soundAlertTextBoxt.Text
  ...
End Sub

Endelig vil du sikkert gerne gemme værdien til næste gang, så i din hoved form skal du skrive:

Sub Form_OnClosing(...)
  ...
  SystemSettings.Instance.Save()
  ...
End Sub
Avatar billede madssch Nybegynder
09. marts 2006 - 13:37 #12
Okay:

Private Sub MainForm_Load ()

    Dim SoundAlertActive As String = SystemSettings.Instance.SoundAlertActive
    Dim PopupAlertActive As String = SystemSettings.Instance.PopupAlertActive

End Sub

Forsøger jeg at kalde SoundAlertActive i en anden Sub, kan den ikke genkende den?
Avatar billede clausc Nybegynder
09. marts 2006 - 13:43 #13
Alle de steder du vil aflæse den globale setting skal du kalde
SystemSettings.Instance.SoundAlertActive

Du skal vel bruge den til noget?

Private Sub MainForm_Load ()
    TextBox1.Text = SystemSettings.Instance.SoundAlertActive
    TextBox2.Text = SystemSettings.Instance.PopupAlertActive
End Sub

Private Sub Button1_Clicked(SystemSettings.Instance.SoundAlertActive)
  madssch_sound_player.Play()
End Sub

osv osv
Avatar billede madssch Nybegynder
09. marts 2006 - 13:48 #14
Eksempel:

    Private Sub MainForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim SoundAlertActive As String = SystemSettings.Instance.SoundAlertActive
        Dim PopupAlertActive As String = SystemSettings.Instance.PopupAlertActive

        MessageBox.Show(SoundAlertActive)

    End Sub

Min MessageBox indeholder ikke noget..?
Avatar billede clausc Nybegynder
09. marts 2006 - 14:00 #15
Åh! Jeg så ikke præcis hvad du har skrevet i din kode. Du mangler en Constructor til klassen. Normalt er en constructor public; men singletons har private constructors (det er det der sikrer du altid får den samme instans).

Men hvis du ændrer navnet på LoadSettings() til SystemSettings(), så burde den blive klassens (private) constructor, og så skulle det gerne soille.
Avatar billede clausc Nybegynder
09. marts 2006 - 14:03 #16
Nej, checkede lige dokumentationen. VB vil ha' at constructors hedder New(). Så den metode du har der hedder LoadSettings skal omdøbes til New().
Avatar billede madssch Nybegynder
09. marts 2006 - 14:12 #17
Ja, åbenbart. Nu virker det i hvert fald.

Synes da det giver lidt mærkelig navngivning..? Nå, what the hell...

Det er vel lige meget, hvad jeg kalder den sub, som gemmer koden, ikke..?
Avatar billede clausc Nybegynder
09. marts 2006 - 14:14 #18
Jo. Men Save er nok ikke helt tosset :) Men jeg fik osse lige genopfrisket lidt VB...
Jeg lægger dette som et svar så :)
Avatar billede madssch Nybegynder
09. marts 2006 - 14:17 #19
Jeps, tusind tak for hjælpen!

Håber jeg har fået strikket det sådan sammen, at jeg kan genbruge meget af det til et senere projekt.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester