none
Buttons in Formular automatisch erzeugen RRS feed

  • Frage

  • Hallo Leute,

    ich habe ein Problem: Ich möchte ein Formular erzeugen, das beim Aufruf die Namen der Hyper-V Hosts aus der Datenbank des SCVMM liest und abhängig von der Anzahl der gefundenen Server die Größe des Formulars festlegt. Dann sollen dort für jeden Server eine Schaltfläche, mit dem Namen des Servers in fünf Spalten und soviel Zeilen, wie benötigt eingefügt werden. Bei Betätigung einer Schaltfläche soll dann später eine Funktion ausgeführt werden, die den Namen des Servers übergeben bekommt. Zur Zeit habe ich ein "Write-Host" eingesetzt. Es wird immer nur der Name der letzten Schaltfläche ausgegeben.

    Wie bekomme ich es hin, dass die Schaltflächen die eigenen Namen ausgeben/ich die Objekte in der Schleife indizieren und hochzählen kann? In C#, VB und VBA geht es doch auch. Ich habe bisher einiges versucht, was aber keinen Erfolg brachte:
    - $OKButton[$i]
    - $OKButton+$i.ToString()
    ...

    Mein Code:

    # Schleife
    $Zeile = 1
    $Spalte = 1
    for ($i = 0; $i -lt $Anzahl; $i++) {
        $j = [Math]::Truncate($i/5)    
        $k = $i % 5
        $OKButton = New-Object System.Windows.Forms.Button
        $OKButton.Location = New-Object System.Drawing.Size(($k*100+6),($j*25+6))
        $OKButton.Size = New-Object System.Drawing.Size(100,25)
        $OKButton.Text = $HVs[$i]
        $OKButton.Name = "Button$i"
        $OKButton.BackColor = "Green"
        $OKButton.ForeColor = "White"
        $OKButton.DialogResult = "OK"
        $OKButton.Add_Click({ Write-Host $OKButton.Name})
        $objForm.Controls.Add($OKButton)
    }

    Grüße,

    Thomas

    Dienstag, 26. Juni 2018 15:22

Antworten

  • .Net unterstützt keine Indizierung von Steuerelement mehr.
    Du musst neue Elemente mit eindeutigem Namen erstellen, was du ja tust.
    Für den Zugriff musst du dir die Steuerelemente dann aber in einem eigenen Array merken, auf das du dann per Index wieder zugreifst.

    Als OK-Button kann man nur einen definieren. Sobald du dies ein weiteres Mal machst, wird die erste Zuordnung wieder aufgehoben.
    Schließlich gilt der OK-/Cancel-Button als Bestätigung/Abbruch des Dialoges.

    Dienstag, 26. Juni 2018 16:48

Alle Antworten

  • .Net unterstützt keine Indizierung von Steuerelement mehr.
    Du musst neue Elemente mit eindeutigem Namen erstellen, was du ja tust.
    Für den Zugriff musst du dir die Steuerelemente dann aber in einem eigenen Array merken, auf das du dann per Index wieder zugreifst.

    Als OK-Button kann man nur einen definieren. Sobald du dies ein weiteres Mal machst, wird die erste Zuordnung wieder aufgehoben.
    Schließlich gilt der OK-/Cancel-Button als Bestätigung/Abbruch des Dialoges.

    Dienstag, 26. Juni 2018 16:48
  • Hallo bfuerchau,

    vielen Dank für die schnelle Hilfe. Ich habe es nun so gelöst:

    ---------------------------------------------------------------------------------------------------------------------------

    # Array bilden

    [Array]$AllButtons = @()

    # Schleife durch Server-Buttons

    for ($i = 0; $i -lt $Anzahl; $i++) {
        $j = [Math]::Truncate($i/5)                                        # Zeilenindex: geteilt durch 5 und abgerundet    
        $k = $i % 5                                                                # Spaltenindex: Modulo 5
        $Button = New-Object System.Windows.Forms.Button
        $AllButtons += $Button.PSObject.Copy()
        $Button.Location = New-Object System.Drawing.Size(($k*100+6),($j*25+6))
        $Button.Size = New-Object System.Drawing.Size(100,25)
        $Button.Text = $HVs[$i]                                             # Servername auf Button
        $Button.BackColor = "LightGray"
        $Button.ForeColor = "Black"
        $Button.Add_Click({                                                   # Script für Schaltfläche
            if ($this.text -eq (Invoke-Command -ComputerName $this.text {hostname})) {
                $this.BackColor = "Green"
                $this.ForeColor = "White"
            } else {
                $this.BackColor = "Red"
                $this.ForeColor = "White"
            }
    Write-Host $this.Text

        })
        $objForm.Controls.Add($Button)
    }
    ---------------------------------------------------------------------------------------------------------------------------

    Ansprechen kann ich sie nun über $AllButtons[$i]

    Danke und Gruss

    Mittwoch, 27. Juni 2018 11:48
  • Das wundert mich schon, denn du erstellst ja eine Kopie in dein Array, dass du aber nicht in die Controls hinzufügst:

    $AllButtons += $Button.PSObject.Copy()

    Der korrekte Weg ist:
    $AllButtons += $Button

    Da mit
    $button = New-Object ...
    der Inhalt überschrieben wird, der Verweis im Array aber erhalten bleibt.

    Mittwoch, 27. Juni 2018 12:34
  • Ich habe Deinem Hinweis folgend, mein Script angepasst - funktioniert genauso wie mit .PSObject.Copy(). Der Scriptteil, indem ich auf die Buttons wieder zugreife lautet:

    ______________________________________________

    $ButtonAlle.Add_Click({
        for ($i = 0; $i -lt $Anzahl; $i++) {
            $HV = $HVs[$i]
            $AllButtons[$i].BackColor = "LightGray"
            $AllButtons[$i].ForeColor = "Black"
            if ($AllButtons[$i].text -eq (Invoke-Command -ComputerName $HV {hostname})) {
                $AllButtons[$i].BackColor = "Green"
                $AllButtons[$i].ForeColor = "White"
            } else {
                $AllButtons[$i].BackColor = "Red"
                $AllButtons[$i].ForeColor = "White"
            }
    Write-Host $AllButtons[$i].Text $HV
        }
    })
    ________________________________________________________________

    Wie gesagt, Danke für Deine Hilfe.

    Mittwoch, 27. Juni 2018 13:04
  • Ja du hast recht.
    Für PSObject.Copy() muss das Objekt selber eine Clone-Methode verfügbar machen, ansonsten wird nur der Verweis zurückgegeben.
    Insweit hast du Glück gehabt, dass das Button-Object nicht clonable ist.
    Mittwoch, 27. Juni 2018 13:28