Dynamisch erstellte Checkboxen - unterschiedliches Verhalten bei verschiedenen Betriebssystemen

  • VB.NET

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Dynamisch erstellte Checkboxen - unterschiedliches Verhalten bei verschiedenen Betriebssystemen

    Hallo,

    ich bin gerade dabei, ein Server-Manager-Programm zu schreiben, das auch eine Benutzerverwaltung beinhaltet. Mein Problem bezieht sich auf mein Formular "Benutzer_bearbeiten".

    Hier eine Vorschau:

    Hier soll man, nachdem man einen Benutzer ausgewählt hat, die Zugriffsrechte auf angelegte Server verwalten können. Es gibt die Berechtigung "Steuerung" (Starten und Stoppen des Servers) sowie "Einstellungen" (Bearbeiten der Server-Configs). Die Berechtigung "Einstellungen" soll nur jemand bekommen können, der die Berechtigung "Steuerung" hat. Daher wird die Einstellungs-Checkbox aktiviert/deaktiviert, je nachdem ob die Steuerungs-Checkbox angeklickt ist oder nicht. Da natürlich die Anzahl der Server unterschiedlich ist, werden die Checkboxen dynamisch in einem Panel erstellt:

    VB.NET-Quellcode

    1. Private Sub Benutzer_bearbeiten_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    2. CbUserSelect.Items.Clear()
    3. For Each User As UserInfo In ProgramData.Users
    4. 'CbUserSelect.Items.Add(User.Username.ToString & " - " & User.SteamID.ToString)
    5. CbUserSelect.Items.Add(User.Username.ToString)
    6. Next
    7. For SrvNo As Integer = 0 To ProgramData.Servers.Count - 1
    8. If Controls.ContainsKey("TxtServerName" & ProgramData.Servers(SrvNo).ID) = False Then
    9. Dim txt As New TextBox
    10. txt.Name = "TxtServerName" & ProgramData.Servers(SrvNo).ID
    11. txt.ReadOnly = True
    12. txt.BorderStyle = BorderStyle.None
    13. txt.BackColor = Color.White
    14. txt.Text = ProgramData.Servers(SrvNo).Servername
    15. txt.TextAlign = HorizontalAlignment.Center
    16. txt.Font = New Font("Microsoft Sans Serif", 12.0, FontStyle.Regular)
    17. txt.Size = New Size(250, 30)
    18. txt.Location = Size.op_Explicit(New Size(8, 7 + SrvNo * 30))
    19. txt.Parent = PanServerSettings
    20. txt.Show()
    21. End If
    22. If Controls.ContainsKey("ChbServerCtrl" & ProgramData.Servers(SrvNo).ID) = False Then
    23. Dim chbCtrl As New CheckBox
    24. chbCtrl.Name = "ChbServerCtrl" & ProgramData.Servers(SrvNo).ID
    25. chbCtrl.AutoSize = True
    26. chbCtrl.Font = New Font("Microsoft Sans Serif", 12.0, FontStyle.Regular)
    27. chbCtrl.Location = Size.op_Explicit(New Size(300, 11 + SrvNo * 30))
    28. chbCtrl.Parent = PanServerSettings
    29. chbCtrl.Show()
    30. AddHandler chbCtrl.CheckedChanged, Sub() OnCheckedChanged(chbCtrl)
    31. End If
    32. If Controls.ContainsKey("ChbServerEdit" & ProgramData.Servers(SrvNo).ID) = False Then
    33. Dim chbEdit As New CheckBox
    34. chbEdit.Name = "ChbServerEdit" & ProgramData.Servers(SrvNo).ID
    35. chbEdit.AutoSize = True
    36. chbEdit.Font = New Font("Microsoft Sans Serif", 12.0, FontStyle.Regular)
    37. chbEdit.Location = Size.op_Explicit(New Size(407, 11 + SrvNo * 30))
    38. chbEdit.Parent = PanServerSettings
    39. chbEdit.Show()
    40. chbEdit.Enabled = False
    41. End If
    42. Next
    43. TxtSteamID.Enabled = False
    44. TxtUsername.Enabled = False
    45. ChbEnabled.Enabled = False
    46. ChbIsAdmin.Enabled = False
    47. PanServerSettings.Enabled = False
    48. End Sub


    Funktion OnCheckedChanged:

    VB.NET-Quellcode

    1. Private Sub OnCheckedChanged(ByVal ChbCtrl As CheckBox)
    2. Dim SrvNo As Integer = CInt(ChbCtrl.Name.Substring(13))
    3. Dim ChbEdit As CheckBox = DirectCast(PanServerSettings.Controls("ChbServerEdit" & SrvNo), CheckBox)
    4. If ChbCtrl.Checked = False Then
    5. ChbEdit.Checked = False
    6. ChbEdit.Enabled = False
    7. Else
    8. ChbEdit.Enabled = True
    9. End If
    10. End Sub

    Auf meinem Entwicklungs-PC (Win10Pro x64) funktioniert das auch einwandfrei. Wenn ich das Programm aber auf dem Server ausführe (Windows Server 2016 x64), auf dem es später laufen soll, wir beim Anklicken einer beliebigen Steuerungs-Checkbox immer nur die erste Einstellungs-Checkbox aktiviert oder deaktiviert. Ich gebe zu, ich habe zunächst einfach die Anwendung rüber kopiert, was natürlich nicht die feine Art ist, aber auch das Erstellen eines Releases und das Installieren auf dem Server zeigten das gleiche Verhalten. :(

    Kann mir jemand sagen, warum das so ist, und wie das ich Problem gelöst bekomme?

    Vielen Dank! :thumbup:

    cya Igel
    Du versuchst mit Teilstringdaten irgendwelche Controls anzusprechen und Entscheidungen zu treffen. CE-Namen auszuwerten, um daraufhin Entscheidungen zu treffen, ist m.E. eine Fehlkonstruktion. Nimm lieber ein UserControl her, was Servernamentextbox und die CheckBoxen enthält.

    Das Enable/Disable-Prinzip zweifel ich grundsätzlich an. Da komm ich kurz mit meinem Spionage- und Manipulationsprogramm vorbei und reaktiviere die CheckBoxen, die nicht enabled sind und schon kann ich machen, was nicht für mich als User vorgesehen ist. Angemerkt: So ein CE-Manipulationstool ist sehr schnell geschrieben.

    btw:
    • Zum Erstellen von neuen Controls solltest Du sie auch der Control-Sammlung des Formulars hinzufügen: Me.Controls.Add(DasNeuErstellteControl)
    • Vergleiche mit True oder False sind überflüssig: If ChbCtrl.Checked = True -> If ChbCtrl.Checked; If ChbCtrl.Checked = False -> If Not ChbCtrl.Checked
    ##########

    Warum schaust Du mit den IF-Konstrukten bei der CE-Erstellung eigentlich, ob die Controls mit bestimmten Namen schon erstellt wurden? Das MyBase_Load-Event wird nur 1x pro Erstellung gefeuert. Und da ist doch noch gar kein dynamisch erstelltes CE auf dem Form. Oder ist das schonmal passiert, dass es ohne die IFs ein Problem auftrat?

    Warum verwendest Du bei z.B. chbEdit.Location = Size.op_Explicit(New Size(407, 11 + SrvNo * 30)) ein Size.Konstrukt, wenn ein Point-Konstrukt viel sinnvoller wäre?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „VaporiZed“ ()

    Vielen Dank für eure Antworten!

    @VB1963 DGV (damit ist wohl DataGridView gemeint) kannte ich bisher nicht. Ich denke, das beantwortet die Frage ;) Sieht aber interessant aus und werd ich mir mal anschauen :thumbup:
    @VaporiZed Du weißt ja schon aus meinen anderen Posts, dass ich nicht so der VB-Crack bin ;) Ich war schon stolz, dass ich das soweit alleine hinbekommen hab :saint:

    Davon dass es eine Control-Sammlung in einem Formular gibt, wursste ich nichts, aber stimmt natürlich, dass das dann auch dort "vermerkt" sein sollte.
    Zum Thema Size.Konstrukt: ich hab das so mal irgendwo gesehen und es hat funktioniert (auch wenn mir das doch zu kompliziert für eine einfache Zuordnung erschien), daher bin ich davon ausgegangen, dass das schon richtig ist :huh: Wie müsste das denn aussehen?

    cya Igel

    Igel schrieb:

    Davon dass es eine Control-Sammlung in einem Formular gibt, wursste ich nichts
    Dann weißt Du wohl nicht, was Dein Code genau macht:

    VB.NET-Quellcode

    1. If Controls.ContainsKey("TxtServerName" & ProgramData.Servers(SrvNo).ID) = False Then

    Igel schrieb:

    Wie müsste das denn aussehen?
    Viel einfacher. Und auch naheliegender. chbEdit.Location ist vom Typ Point. Also: chbEdit.Location = New Point(407, 11 + SrvNo * 30))
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.
    Naja

    VB.NET-Quellcode

    1. If Controls.ContainsKey("TxtServerName" & ProgramData.Servers(SrvNo).ID) = False Then

    wird wohl überprüfen, ob es die Controls schon gibt.
    Was ich mit der Control-Sammlung meinte, ist, dass ich eigentlich dachte, wenn ich Controls anlege, dass die dann automatisch bekannt sind, und nicht erst noch der Sammlung hinzugefügt werden müssen.

    chbEdit.Location = New Point(407, 11 + SrvNo * 30)) an sowas hatte ich gedacht, danke :)
    Falsch gedacht. Kann ja genauso sein, dass Du in Deinem Formular ein Control erstellst, dieses aber einem anderen Formular hinzufügen willst.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.
    Stimmt, daran hatte ich nicht gedacht..

    @VB1963:
    Ich habe jetzt mal wenig mit DGVs herumgespielt. Wie ist der Change-Event und wie kann ich denn die Checkboxen auswerten bzw ändern?
    folgendes hab ich mal versucht, aber da scheint irgendwie was anderes zu passieren als gedacht..
    Das Formular sieht jetzt so aus (inkl. der Spaltenübersicht):


    Hier mit ichs mal versucht, aber ich bekomme im "false" angezeigt, egal ob ich eine Checkbox anklicke oder nicht..

    VB.NET-Quellcode

    1. Private Sub DGVServerSettings_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles DGVServerSettings.CellClick
    2. If DGVServerSettings.Columns(e.ColumnIndex).Name = "ServerCtrl" Then
    3. Console.WriteLine(DGVServerSettings.Rows(e.RowIndex).Cells(2).Value)
    4. End If
    5. 'DGVServerSettings.RefreshEdit()
    6. End Sub


    Wie muss das richtig aussehen, damit das gescheit funktioniert?

    cya Igel
    Nein, das geht so nicht, weil Du Dich noch im Bearbeitungsmodus der Zeile befindest. Erst wenn Du die Zeile verlässt, werden die Werte der Zeile übernommen und können ausgewertet werden.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.

    Igel schrieb:

    ich bin gerade dabei, ein Server-Manager-Programm zu schreiben, das auch eine Benutzerverwaltung beinhaltet.
    Sowas täte ich mal eine Datenverarbeitung nennen, weil dassis äusserst sinnvoll, Benutzer und Rechte, evtl. Gruppen, Server, und was sonst noch so alles anfallen mag, also alles dieses als Datensätze aufzufassen und zu modellieren.
    Immerhin bist du nun auch schon fast so weit, den Switch von viele generierte Panel hin zu eim Datagridview zu vollziehen.
    Da könnte man denn auch mit Databinding anfangen - das kann alles sehr elegant werden, wenn richtig angefasst.

    Hmm - aber ich denke eiglich, um richtig einzusteigen musste erst noch weitere Erfahrungen machen mit den Begrenztheiten deines Ansatzes.
    Aber wenns sehr mühselig wird, Benutzer auszuwählen, und deren Rechte zu bearbeiten, und laden und Speichern und solche Sachen - dann kannste dich vlt einfach nochmal melden.