Labels im Code erstellen und runterschieben

  • VB.NET
  • .NET (FX) 4.5–4.8

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

    Labels im Code erstellen und runterschieben

    Guten Tag,

    ich bin nun wieder mal dazu gekommen, etwas neues zu lernen.
    Ich möchte ein Programm schreiben, welches für mich z.B eine Art Textarea/Textblock darstellt und man somit z.B News in sein Programm einbinden kann. z.B soll dies dann so aussehen:

    Alt: Serverarbeiten um 20:15 Uhr

    Nun möchte ich News hinzufügen:

    Neu: Serverarbeiten um 22:15 Uhr
    Alt: Serverarbeiten um 20:15 Uhr

    Der zweite Label wird runtergeschoben und dafür wird ein neuer erstellt. Dies soll unendlich lang gehen. Wie funktioniert so ein Prinzip? Ich möchte des nicht nur mit Labels lernen, sondern auch mit Buttons. Ich habe mir das so vorgestellt(provisorischer Code):

    VB.NET-Quellcode

    1. ​Dim CountLast as Integer
    2. Dim CountCurrent as Integer
    3. If not CountLast = CountCurrent then
    4. Label1.create("Testlabel")'keine echte Funktion, nur Theorie
    5. Label1.location(x+5,y+5)
    6. End if


    Das könnte purer Bullshit sein, so sieht das jedenfalls für mich aus.
    Also.. Wie genau könnte man das anstellen oder besser gesagt.. wie heißt sowas, damit ich mich erkundigen kann?
    Wenn ich eine Frage stelle, habe ich sie bereits gegooglet. Ja, es kommt vor, dass ich die Antwort übersehe. Ja, es kommt vor, dass ich sie nicht verstehe. Deshalb bin ich hier. Wenn dies eure Frage war, dann antwortet bitte nicht. Es stiehlt sämtliche Motivation.
    naja du könntest anstelle von Labels, auch eine MultilineTextbox oder eine RichTextbox verwenden, dann müssten keine Labels geschoben werden, sonder nur codeseitig in der jeweiligen textbox gescrollt werden
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    Oder mit ListBox oder ListView oder DGV immer in die erste Zeile schreiben und den Rest runterschieben.
    Aber um zu Deiner Ursprungsfrage zurückzukommen:
    Du willst immer neue Controls erstellen und ggf. die anderen umplatzieren, richtig?
    Also: Zuerst machst Du Dir ne List(Of Label). Damit Du die Bälger irgendwie im Zaum halten kannst ;)
    Dann für die Form:

    VB.NET-Quellcode

    1. Dim NewLabel As New Label
    2. 'hier noch viele Eigenschaften inkl. Position festlegen, ggf. noch Events registrieren, wenn Du z.B. Buttons statt Labels nutzt und denen Funktionalität einhauchen willst
    3. Me.Controls.Add(NewLabel)
    4. For Each Lbl in LabelList
    5. Lbl.Top += 5
    6. Next
    7. LabelList.Add(NewLabel)

    So die ungefähre Vorgehensweise.
    Allerdings sollten die CEs (Control Elements, also Labels, Buttons, wasauchimmer) irgendwann ggf. gekillt werden, wenn sie nicht mehr gebraucht werden, weil sie aus der Form verschwinden, es für Dich zu viele werden, ...
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @asusdk
    Natürlich könnte ich das, aber es geht mir darum, etwas zu lernen. :'3

    @VaporiZed
    Oh mein Gott, du hilfst mir damit einen riesen Schritt weiter.
    Ich schaue mich damit mal ein wenig um, ich melde mich wenn ich euch wieder brauche!
    Wenn ich eine Frage stelle, habe ich sie bereits gegooglet. Ja, es kommt vor, dass ich die Antwort übersehe. Ja, es kommt vor, dass ich sie nicht verstehe. Deshalb bin ich hier. Wenn dies eure Frage war, dann antwortet bitte nicht. Es stiehlt sämtliche Motivation.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Sekki“ ()

    paar Tips:
    • für komplexe Controls - etwa bestehend aus Label und Button - empfiehlt es sich, ein UserControl zu gestalten. Dann hat man alles mit einem New() - Aufruf beisammen.
    • Auch zu überlegen, als ContainerControl ein FlowlayoutPanel zu nehmen - dann brauchste dich auch um die Positionierung nicht mehr zu kümmern.
    • Eine ControlCollection hat nicht nur .Add(), sondern auch eine .Insert() - Methode - je nachdem würde dann das neue Control oben oder unten angefügt.
    • Control.Dispose() entfernt das gelöschte Control auch aus der ControlCollection
    @VaporiZed
    @ErfinderDesRades
    Die Idee mit dem FlowLayoutPanel kannte ich noch nicht, dass ist einfach nur genial. Ich wollte eigentlich vor längerer Zeit man die Zeit nutzen, um mich durch alle Controls durch zu schlagen, aber dann habe ich es doch nicht getan. Anscheinend sind meine Hauptprobleme immer bereits von selbst gelöst.
    Sehr schön! Soweit so gut. Ich habe nun folgenden Code:

    VB.NET-Quellcode

    1. ​Dim NewButton As New Button
    2. Count += 1 'Damit die Buttons "Test1", "Test2" heißen usw.
    3. NewButton.Text = "Test" & Count
    4. FlowLayoutPanel1.Controls.Add(NewButton)


    Ich habe ebenfalls eine Test1_Click Sub erstellt, um herauszufinden, wie man einem neu erstellten Button einen Handler zuweist und dies ist dabei herausgekommen:

    VB.NET-Quellcode

    1. ​AddHandler NewButton.Click, AddressOf Test1_Click


    Ich finde es fast schon faszinierend, wie einfach sowas geht und wie ich mir damals sonst immer den Code im Kopf vorgestellt habe. Eines begreife ich jedoch weiterhin nicht: Wenn ich 20 Buttons im FlowLayoutPanel habe, muss ich dann 20 Subs voranfertigen, damit die Buttons diese nutzen können? Rein von der Theorie her, klingt dies am sinnvollsten, aber ist dies die "saubere" Art zu coden?

    Und:

    Ist es möglich, statt "Test1_Click" einfach anzugeben: "Test & Count & "_Click""? Sonst müsste ich theoretisch ja eine Abfrage machen, ob der Button schon existiert und das wäre ziemlich unelegant, wenn man mich fragen würde.. Wie ich bereits sagte, nutze ich eure Informationen zum lernen! Deshalb könnt ihr ruhig sehr ins Detail gehen, ich werde mich bei Begriffe die ich nicht kenne schon selbst im Internet informieren!
    Wenn ich eine Frage stelle, habe ich sie bereits gegooglet. Ja, es kommt vor, dass ich die Antwort übersehe. Ja, es kommt vor, dass ich sie nicht verstehe. Deshalb bin ich hier. Wenn dies eure Frage war, dann antwortet bitte nicht. Es stiehlt sämtliche Motivation.
    mit AddHandler kannst du alle Klickse auf dieselbe Sub leiten.
    In dieser Sub kannst du das Sender-Argument untersuchen - das ist ja jeweils ein anderer Button (halt der der das Event gesendet hat). Anhand dieser Unterscheidung kannst du dann natürlich den Code beliebig verzweigen oder whatever.
    Hier mal grad Beispiel, wie sowas aussieht:

    VB.NET-Quellcode

    1. Private Sub Test1_Click(sender As Object, e As EventArgs)
    2. Select Case True
    3. Case sender Is btReLoad : Dts.Fill()
    4. Case sender Is btSave : Dts.Save(Me)
    5. Case sender Is btTest : Class1.Test1()
    6. Case sender Is btTest1
    7. Case sender Is btTest2
    8. Dts.Tables("Table1").Clear()
    9. GC.Collect()
    10. Case sender Is btTest3
    11. End Select
    12. System.Media.SystemSounds.Asterisk.Play()
    13. End Sub




    Sekki schrieb:

    st es möglich, statt "Test1_Click" einfach anzugeben: "Test & Count & "_Click""?
    Nein - hier verwechselst du 2 völlig unterschieliche Ebenen.
    Test1_Click - s.o., Zeile #1 - ist ein Name im Code, ist also Code, und der Compiler übersetzt das.

    "Test & Count & "_Click" ist ein String - kannste zb einer Variablen zuweisen:

    VB.NET-Quellcode

    1. Dim s = "Test & Count & "_Click"
    Das kann der Compiler übersetzen, und dann enthält s den Wert (zb.) "Test13_Click". Also er kann den Code mit der Zuweisung des Strings an die Variable s übersetzen.
    Den String selbst aber nicht.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    @Sekki, Deine Frage lässt erahnen das Du für jeden Button/Label einen Handler hinzufügen willst. Was @ErfinderDesRades aber meint ist, 1 Handler für ALLE Buttons oder Labels.

    Hier mal ein Beispiel, wie ich es in einem meiner Programme gemacht habe:
    Sub für das Erstellen von Labels:

    VB.NET-Quellcode

    1. ​Private Sub AddLbLControl(flp As FlowLayoutPanel, tx As String, backCol As Color, id As Integer)
    2. flp.SuspendLayout()
    3. Dim txt = If(tx, "Untitled")
    4. Dim lb = New Label With {.Text = txt, .Tag = id, .BackColor = backCol,
    5. .ForeColor = Color.Black, .Size = New Size(200, 70),
    6. .BorderStyle = BorderStyle.FixedSingle,
    7. .Font = New Font("Segeo UI", 12)}
    8. AddHandler lb.Click, AddressOf OnClickLB
    9. flp.Controls.Add(lb)
    10. flp.ResumeLayout()
    11. End Sub

    der Handler:

    VB.NET-Quellcode

    1. ​Private Sub OnClickLB(ByVal sender As Object, ByVal e As EventArgs)
    2. Dim id = sender.tag
    3. If id >= 20000 AndAlso id <= 99999 Then
    4. Dim row = Dts.Guest.GetForeign(id)
    5. If MessageBox.Show(row.Name & " Möchten Sie sich abmelden?", "MICRODYN-NADIR GmbH", MessageBoxButtons.YesNo) = DialogResult.Yes Then
    6. flpPresence.Controls.Remove(sender)
    7. row.Delete()
    8. mDAL.UpdateGuest(Dts.Guest)
    9. Else
    10. Return
    11. End If
    12. Else
    13. _BolPresent = Dts.Employee.GetPresent(id)
    14. If _BolPresent Then
    15. If MessageBox.Show(sender.text & " Möchten Sie sich abmelden?", "MICRODYN-NADIR GmbH", MessageBoxButtons.YesNo) = DialogResult.No Then Return
    16. AddLbLControl(flpAbsence, sender.Text, Color.AliceBlue, id)
    17. flpPresence.Controls.Remove(sender)
    18. Dts.Employee.First(Function(rw) rw.EmployeeID = id).Present = False
    19. mDAL.UpdateEmployee(Dts.Employee)
    20. Else
    21. AddLbLControl(flpPresence, sender.Text, Color.YellowGreen, id)
    22. flpAbsence.Controls.Remove(sender)
    23. Dts.Employee.First(Function(rw) rw.EmployeeID = id).Present = True
    24. mDAL.UpdateEmployee(Dts.Employee)
    25. End If
    26. End If
    27. End Sub


    Aufruf ist dann so:

    VB.NET-Quellcode

    1. ​AddLbLControl(flpAbsence, EmployeeText, Color.AliceBlue, row.EmployeeID)


    das kannst auch in einer Schleife aufrufen
    "Hier könnte Ihre Werbung stehen..."
    Ist nicht strict off ;(
    sender ist doch das Label vom Typ object oder was hab ich da falsch?

    EDIT:
    Sender is natürlich ein Object und das Label, was das Event aufruft ist ein Control.
    Der Compiler hat keinen Stress damit weil auch ein Control von Object erbt.
    Aber wie gehts richtig?
    "Hier könnte Ihre Werbung stehen..."

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

    z.B. mit DirectCast(sender, Control)
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    ich muss @ErfinderDesRades mal wieder Recht geben. Global ist Strict immer On, hier in dem Proejct wars off, warum auch immer....
    Habs jetzt geändert und nun erstmla die Fehler beheben... Mann Mann

    EDIT:
    So, hab die Sub jetzt so abgeändert.

    VB.NET-Quellcode

    1. ​Private Sub OnClickLB(ByVal sender As Object, e As EventArgs)
    2. Dim lb As Label = DirectCast(sender, Label)
    3. Dim id = DirectCast(lb.Tag, Integer)
    4. Dim tx = DirectCast(lb.Text, String)
    5. If id >= 20000 AndAlso id <= 99999 Then
    6. Dim row = Dts.Guest.GetForeign(id)
    7. If MessageBox.Show(row.Name & " Möchten Sie sich abmelden?", "MICRODYN-NADIR GmbH", MessageBoxButtons.YesNo) = DialogResult.Yes Then
    8. flpPresence.Controls.Remove(lb)
    9. row.Delete()
    10. mDAL.UpdateGuest(Dts.Guest)
    11. Else
    12. Return
    13. End If
    14. Else
    15. _BolPresent = Dts.Employee.GetPresent(id)
    16. If _BolPresent Then
    17. If MessageBox.Show(tx & " Möchten Sie sich abmelden?", "MICRODYN-NADIR GmbH", MessageBoxButtons.YesNo) = DialogResult.No Then Return
    18. AddLbLControl(flpAbsence, tx, Color.AliceBlue, id)
    19. flpPresence.Controls.Remove(lb)
    20. Dts.Employee.First(Function(rw) rw.EmployeeID = id).Present = False
    21. mDAL.UpdateEmployee(Dts.Employee)
    22. Else
    23. AddLbLControl(flpPresence, tx, Color.YellowGreen, id)
    24. flpAbsence.Controls.Remove(lb)
    25. Dts.Employee.First(Function(rw) rw.EmployeeID = id).Present = True
    26. mDAL.UpdateEmployee(Dts.Employee)
    27. End If
    28. End If
    29. End Sub


    Der Compiler ist happy. Frage ist, ob das ganze gecaste am Anfang benötigt wird, oder obs einen eleganteren weg gibt.
    Den Tag und Text des aufrufenden Labels benötige ich aber...
    "Hier könnte Ihre Werbung stehen..."

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „MichaHo“ ()

    @ErfinderDesRades
    @MichaHo
    Danke, dass ihr euch so viel Zeit für mich nehmt. Es ist schön, wenn man genug Stoff zum Üben bekommt. Ich werde mich da mal durchschlagen und versuchen die Schnipsel vom Sinn her zu verstehen.

    @VaporiZed
    Also, jetzt muss ich doch mal fragen. Was genau bedeutet eigentlich "casten"? Ihr nutzt dieses Wort immer wieder und wieder und oft auch in anderen Threads. Ich finde nur Sachen wie "Typen Casten, casting types usw." und verstehe den Zusammenhang nicht. Meines Wissens heißt "Cast" sowas wie.. Einnehmen. "Casting" heißt "Guss". Sind das nun beides die selben Kontexte oder wie soll ich das verstehen? Kennt ihr vielleicht sogar eine Seite, wo man sich das vernünftig durchlesen kann, ohne viel zu wissen?

    Auch, wenn man VB.net nicht so viel anstellen kann wie mit C++, bin ich fest entschlossen, dass man mit VB.net jedenfalls mehr tun kann, als man denkt. Deshalb möchte ich dies zur meiner Hauptsprache machen(C# kommt danach). Daher frage ich so viel.
    Wenn ich eine Frage stelle, habe ich sie bereits gegooglet. Ja, es kommt vor, dass ich die Antwort übersehe. Ja, es kommt vor, dass ich sie nicht verstehe. Deshalb bin ich hier. Wenn dies eure Frage war, dann antwortet bitte nicht. Es stiehlt sämtliche Motivation.