Mitgliederverwaltung - Hilfe bei der Erstellung sauberen Codes

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

Es gibt 244 Antworten in diesem Thema. Der letzte Beitrag () ist von tragl.

    DerSmurf schrieb:

    Aber wenn ich die einkaufrow vorher fertig mache und mit .editcurrent Anzeige, ist sie ja bereits gespeichert.
    "Gespeichert" ist bisserl übertrieben.
    Sie ist ins Dataaset übernommen - gespeichert ist ja erst, wenn Dataset.WriteXml, oder wenn an DB gesendet.

    DerSmurf schrieb:

    Könntest du mir kurz erklären, warum meine Variante (mit Übergabe der PersonRow) schlecht ist?
    Ich hab gedacht, das würde Probleme machen mit der Übergabe.
    Und die Anzeige der EinkaufRow mit all ihren ChildRows stelle ich mir mit Databinding auch sehr komfortabel zu designen vor.
    Aber wenn das auch mit einer übergebenen PersonRow ebenso einfach zu bewerkstelligen ist - warum nicht?

    ErfinderDesRades schrieb:

    Ich hab gedacht, das würde Probleme machen mit der Übergabe.

    Nein überhaupt nicht. Ich bin mir nur nicht sicher, ob ichs richtig mache, bzw. ob das was ich mache im Sinne des Erfinders ist (siehe Frage 2)

    ErfinderDesRades schrieb:

    Und die Anzeige der EinkaufRow mit all ihren ChildRows stelle ich mir mit Databinding auch sehr komfortabel zu designen vor.

    ist ja bei mir auch. Ich brauche nur eine gefilterte BS an die Artikel (IsChoosen = True) und muss die Labels mit Kundendaten an die Property binden. Das passt schon.
    Also alles gut - lassen wir bei der PersonRow und kommen zu Frage Nummer2:

    Wenn ich mit meiner oben geposteten Lösung die frmFinishOrder anzeige, wird der korrekte Kunde (die richtige PersonRow) angezeigt.
    Öffne ich die frmFinishOrder im Anschluss erneut, mit einem anderen frmVerkauf.BsPerson.Current, wird mir auf der frmFinishOrder wieder die PersonRow vom ersten mal angezeigt.
    Gleiches habe ich bei einer Checkbox auf frmFinishOrder. Diese ist im Designer auf Visible=False.
    Im Load Event prüfe ich dann: CBDatenschutz.Visible = Dts.Artikel.Any(Function(x) x.IsChoosen AndAlso x.Bezeichnung = "DAV Neuanmeldung")und lasse sie ggf anzeigen. Hier verhält es sich genauso.
    Die Visible Property ist bei jeder Anzeige der frmFinishOrder so, wie sie es bei der ersten Anzeige dieser Form war.
    Mir ist klar, dass ich beide Probleme mit einem anderen Aufruf (und eben einer Instanzierung der frmFinishOrder) lösen kann:

    VB.NET-Quellcode

    1. Private Sub FinishOrder()
    2. Dim rwPerson = BSPerson.At(Of PersonRow)
    3. Dim FinishOrder As New frmFinishOrder
    4. With FinishOrder
    5. .SetrwPerson = rwPerson
    6. .ShowDialog()
    7. End With
    8. End Sub


    Aber wie löse ich das Problem, wenn ich die Form als MdiChild angezeigt haben möchte?
    Ist das hier dann die richtige Lösung? (es funktioniert, aber @tragl sagte eine Instanzierung sei nicht notwendig. Jedoch tauchen ja hier gerade die gleichen Probleme auf, die auch auftreten, wenn ich nicht die MDI Geschichte benutze und meine Forms nicht vor dem Anzeigen instanziere. Deswegen bin ich verwirrt.

    VB.NET-Quellcode

    1. Private Sub FinishOrder()#
    2. Dim rwPerson = BSPerson.At(Of PersonRow)
    3. Dim FinishOrder As New frmFinishOrder
    4. With FinishOrder.
    5. SetrwPerson = rwPerson
    6. .ShowMdiChild
    7. End With
    8. End Sub

    DerSmurf schrieb:

    sagte eine Instanzierung sei nicht notwendig

    aber du instanziierst doch -> Zeile 3

    mal ohne probiert?
    Im Übrigen: Bei Dialogen:

    VB.NET-Quellcode

    1. Using dlg As New frmFinishOrder
    2. dlg.SetrwPerson = rwPerson
    3. If dlg.showdialog() <> Dialogresult.OK Then Return
    4. 'ggf. weiteren Code ausführen, wenn DialogResult OK war
    5. End Using

    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    DerSmurf schrieb:

    Wenn ich mit meiner oben geposteten Lösung ...
    Da "oben" sind so viele Lösungen gepostet... - kannst du genauer angeben, was du meinst? Am liebsten einen aktuellen Code-Auszug - ich gehe immer davon aus, dass in Threads geposteter Code nach wenigen Tagen so nicht mehr existiert.

    DerSmurf schrieb:

    Öffne ich die frmFinishOrder im Anschluss erneut, mit einem anderen frmVerkauf.BsPerson.Current, wird mir auf der frmFinishOrder wieder die PersonRow vom ersten mal angezeigt.
    Nanu? Ich denk, du übergibst die PersonRow? Wie kann er dann eine anzeigen, die er das letzte Mal übergeben bekommen hatte?

    ErfinderDesRades schrieb:

    - ich gehe immer davon aus, dass in Threads geposteter Code nach wenigen Tagen so nicht mehr existiert.

    Nachdem ich hier was poste, höre ich auf weiterzumachen, damit so etwas nicht passiert.

    tragl schrieb:

    aber du instanziierst doch -> Zeile 3
    mal ohne probiert?

    Ja, ich habs ohne probiert, dann tritt das oben beschriebene Verhalten auf. Sauber laufen tuts nur mit instanzierung.

    Also ich lad die Solution mal hoch. Man sieht das "Fehlverhalten" wenn man folgendes tut:
    Ich wähle auf der frmVerkauf den Kunden Achim Meyer aus und packe einmal DAV Marke Erwachsen in den Warenkorb, es wird automatisch der Artikel DAV Neuanmeldung hinzugefügt.
    Dann klick auf abschließen. Dahinter ist folgender Code:

    VB.NET-Quellcode

    1. Private Sub FinishOrder()
    2. Dim rwPerson = BSPerson.At(Of PersonRow)
    3. frmFinishOrder.SetrwPerson = rwPerson
    4. frmFinishOrder.ShowMdiChild
    5. 'Dim FinishOrder As New frmFinishOrder
    6. 'With FinishOrder
    7. ' .SetrwPerson = rwPerson
    8. ' .ShowMdiChild
    9. 'End With
    10. End Sub

    Es wird die frmFinsihOrder angezeigt.
    Hier gibt es eine Checkbox (CBDatenschutz). Diese ist im Designer auf Visible = False. Im FormLoad Event wird dann folgendes geprüft:
    CBDatenschutz.Visible = Dts.Artikel.Any(Function(x) x.IsChoosen AndAlso x.Bezeichnung = "DAV Neuanmeldung")
    und die Checkbox entsrechend angezeigt, oder eben nicht. In diesem Fall wird sie natürlich angezeigt.
    Wenn ich nun den zurück Button betätige (Code: frmVerkauf.ShowMdiChild) und den Kunden Hans Hansi auswähle, wird der Artikel DAV Neuanmeldung entfernt und DAV Verzug hinzugefügt.
    Ein erneuter Klick auf abschließen und es wird in der frmFInsihOrder die Checkbox angezeigt (obwohl die Bedingung false ist) und als Kunde wird Achim Meyer angezeigt.
    Durch Einzelschritt habe ich festgestellt, dass das Form Load Event nur im allerersten Aufruf von frmFinishOrder.ShowMdiChild erreicht wird. Bei allen weiteren Anzeigen feuert das LoadEvent nicht.
    Instanziere ich die frmFinishOrder vor dem Anzeigen, läuft alles wie es soll.

    Daher stellt sich mir die Frage:
    Ist die Instanzierung dann der richtige Weg? Oder gibt es einen Weg die frmFinishOrder zu "töten"? (es funktioniert mit der Instanzierung, aber @tragl sagte dies sei nicht notwendig. Jedoch tauchen ja hier gerade die gleichen Probleme auf, die auch auftreten, wenn ich nicht die MDI Geschichte benutze und meine Forms nicht vor dem Anzeigen instanziere. Deswegen bin ich verwirrt.
    Dateien

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

    Kein Problem, nur Verwirrung.

    Denn nach meiner Frage in Post 148:
    Außerdem habe ich noch eine Frage: Warum muss ich mit der MDI Geschichte hier die Forms vorher nicht initialisieren? (hier meine ich natürlich instanzieren)

    kam von @VaporiZed die eindeutige Antwort (Post 149):
    Du hast recht: Weil an der Stelle genau mit dem Dreck gearbeitet wird, den man eben nicht nutzen sollte: thread-dependent-properties (s. Warum »Form1.Show« und Co. einem irgendwann ins Bein schießen). Du solltest dringend dort den Dir bekannten Instanziierungsvorgang vornehmen.


    Von dir @tragl kam dazu dann in Post160 die Antwort:
    wird nicht instanziiert - funzt aber so, denn das Form wird einmal geöffnet und in jedem Fall wieder geschlossen. Ein doppeltes Öffnen geht damit nicht, sondern es wird ja hingewechselt falls es schon offen ist.


    Verwirrung entsteht bei mir nun, da ich nicht weiß, was denn jetzt stimmt.
    Alles klar. Aber bitte verzeih - ich hab dann noch eine Verständnisfrage.
    Wenn ich eine Form instanziiere und mittels .show, oder .showdialog aufrufe, wird diese Instanz doch zerstört, sobald die angezeigte Form geschlossen wird.
    Das passiert ja hier nicht. Wenn ich 10 mal die frmFinishOrder öffne, habe ich doch auch 10 Instanzen dieser Form, die dann erst beim schließen des Programmes zerstört werden, oder habe ich hier einen Denkfehler?

    Das ist jetzt bei diesem Mini Programm hier wahrscheinlich wurscht, aber ich habe vor im Anschluss an das Projekt hier mein MainProjekt auf MDI umzustellen.
    Kann es hier nicht zu Problemen kommen, wenn das Programm den ganzen Tag läuft und irgendwann 100te Form Instanzen existieren?

    Sollte ich da nicht beim verlassen einer Form / bzw. beim Anzeigen einer neuen Form, die aktuelle irgendwie töten?
    Alles klar. Ich danke dir!
    Dann mache ich mich mal ran, alle Aufrufe mit initialisiierung umzuschreiben.

    und hier kanns weitergehen :o)

    Wenn ich ein DGV mit Daten habe, so ist standardmäßig die erste Zeile ausgewählt.
    An machen Stellen in anderen Programmen unterbinde ich dies mit: ​ArtikelDataGridView.ClearSelection()
    Hier in diesem Programm führe ich den Code im FromLoad Event der frmFinishOrder aus, aber die erste Zeile des entsprechenden DGV ist trotzdem selektiert. Ich vermute daher, dass dies an den Helpers, oder dem Template was hier benutzt wird liegt.
    Wie kann ich da Abhilfe schaffen?
    Hmm, nagut. Machen wir einfach die nächste Frage.
    Ich habe auf meiner frmFinishOrder sowohl KeyDown, als auch KeyPress Event abonniert:

    VB.NET-Quellcode

    1. Private Sub frmFinishOrder_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
    2. MessageBox.Show("KeyDown Event")
    3. End Sub
    4. Private Sub frmFinishOrder_KeyPress(sender As Object, e As KeyPressEventArgs) Handles Me.KeyPress
    5. MessageBox.Show("Keypress Event")
    6. End Sub


    Wenn ich die Form "normal" also mittels .show anzeige, funktioniert alles wie gewohnt. Beide Key Events werden aufgerufen.

    Zeige ich die form innerhalb meines MDI Containers wird kein Key Event erreicht.
    Woran könnte das liegen?

    Edit: Gerade habe ich festgestellt, dass beide Event gefeuert werden, wenn ich auf der Form in eine Textbox schreibe. Ohne diese (also beim anwählen eines anderen Controls) aber nicht.
    Dateien

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

    Jo, die Textbox ist dann wahrscheinlich nicht automatisch das aktive control.
    Bei mir hab ich das so gelöst (ist auch eine Textbox) auf der Childform:

    VB.NET-Quellcode

    1. Private Sub frm_Shown(sender As Object, e As EventArgs) Handles Me.Shown
    2. tbSuche.Select()
    3. End Sub


    Also nachdem die Form vollständig geladen ist, selektiert er die Textbox
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Ohja, auf die Idee bin ich garnicht gekommen. Das geht ja auch.

    Aber gibt es nicht eine andere Lösung, in der die KeyEvents einfach funktionieren - egal was ausgewählt ist?
    Hier in der Anwendung wäre das ja wurscht.

    Aber in meiner Hauptanwendung ist es so, dass ich auf einer TabPage (nach Änderung mit MDIChild) mit Tasteneingabe immer die SucheTB beschreibe.
    Hier gibt es ein DGV, haufen Buttons, eine SuchenTB. Ich müsste ich dann jedem Control im Click Event TBSuche.Select() zuweisen.
    Ist ja bei nem Button kein Akt, nachdem der Code ausgeführt ist, die Textbox auszuwählen.
    Aber im DGV wäre das doof. Da kann ich dann z.B. nicht mit den Pfeiltasten durchscrollen, weil ja die Textbox ausgewählt sein muss.
    Außerdem gehen ja dann Dinge wie DGV Eintrag löschen mit "Del", oder kopieren mit "Strg + K" nur schwerlich.
    Da bin ich überfragt - das müsste man sicher was entwickeln, was der Textbox immer wieder den Focus gibt. Seh' ich aber nicht als normalen Anwendungsfall an.
    In meiner Welt gibt's ne Tastenkombination für eine Suche oder der User muss eben in's Suchfeld reinklicken und dann was eintippen. Das ist ja im WIndows-Explorer etc.
    auch so gelöst.
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    DerSmurf schrieb:

    Wenn ich ein DGV mit Daten habe, so ist standardmäßig die erste Zeile ausgewählt.
    Was ist daran unerwünscht?
    Ich finde es logisch, dass in jedem DGV ein Datensatz der fokussierte/selektierte ist.

    Etwa ein ein ParentChild-View oder ein Detail-View - da müsste man einigen Extra-Aufwand treiben, um konsistent darstellen zu wollen, dass nichts selektiert ist.
    Ich denke da hast du grundsätzlich recht.
    Dieses DGV dient aber lediglich der Anzeige der Artikel im Warenkorb (Table Artikel gefiltert nach choosen = True).
    Da der User mit den Daten nichts machen kann außer angucken (nicht mal was anderes selektieren, da Enabled = False), finde ich in diesem einen Fall die Vorselektierung eher störend.
    Ich habe in all meinen anderen Projekten ein einziges DGV, wo ich diese Selektierung ebenbfalls als störend erachte.
    Da löse ich das Problem mittels ​ArtikelDataGridView.ClearSelection(). Das ändert in diesem Projekt hier aber gar nichts.
    An dieser Stelle hier könnte ich ja notfalls ein anderes Control hernehmen. Zur Laufzeit TextBoxen erzeugen oder sowas, aber im anderen Projekt wäre ein DGV (ohne Selektierung) schon schöner.
    Hast du einen Verdacht, welche Methode verantwortlich ist, dass ArtikelDataGridView.ClearSelection() hier keinen Effekt hat?
    Wo rufst du das denn auf? Im frm_Load oder frm_Shown?
    Probier ma im Shown, die Selection ändert sich auch wenn sich an der Bindingsource was tut

    Oder zur allergrößten Not: pass die Farbe vom Selektieren so an, dass sie "unsichtbar" ist ;)
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Soho. Nach Dummheit im Dienst musste ich anderthalb Wochen auf meinen Laptop verzichten, da dieser beim "PCWiederHeileMacher" schlafen musste. Nun kann ich euch endlich weiter auf den Sack gehen :o)

    tragl schrieb:

    Wo rufst du das denn auf? Im frm_Load oder frm_Shown?
    Probier ma im Shown, die Selection ändert sich auch wenn sich an der Bindingsource was tut

    Das Form Show Event ist die Lösung. Hier geht alles so wie ichs erwartet habe.

    Bin zurzeit dabei, die Lieferungen für Marken in meinem Programm zu implementieren und hier so gut wie fertig. Aber dazu eine Frage.

    VB.NET-Quellcode

    1. Dim Lieferantrow = BSLieferant.At(Of LieferantRow)
    2. Dim Artikel = Lieferantrow.GetChildRows("FK_Lieferant_Marke")
    3. Dim Artikel1 = Lieferantrow.GetMarkeRows

    Beide Zeilen hohlen mir alle Artikel (alle ChildRows) zum ausgewählten Lieferanten. Wobei die Methode GetMarkeRows wohl die bessere ist.
    Aber warum heißt diese automatisch generierte? Funktion GetMarkeRows und nicht GetArtikelRows? (Ich hab mir nen Wolf gesucht)...
    Immerhin heißt die zugrundeliegende DataTable ja auch "Artikel" und nicht "Marken"? Liegt es daran, dass ich diese Table mal umbenannt habe? Sollte ich dann auch diese Funktion hier umbenennen?

    Edit: und ich brauche die Artikelrow zu einer LIeferpositionrow. (Hier müsste ja der Artikel / bzw. die Artikelrows die Childrow sein).

    VB.NET-Quellcode

    1. Dim Lieferungrow = BSLieferung.At(Of LieferungRow)
    2. Dim Lieferpositionrow = Lieferungrow.GetLieferpositionRows
    3. For Each Lieferposition As LieferpositionRow In Lieferpositionrow
    4. Dim Artikel = Lieferposition.GetMarkeRows
    5. Next

    Warum gibt es hier keine "GetMarkeRows"?
    Bilder
    • Dts.png

      114,92 kB, 1.920×1.080, 20 mal angesehen

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „DerSmurf“ ()