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.

    Ja, das geht natürlich.
    Aber besser ist ja, den Grund herauszufinden, warum @ErfinderDesRades das rein gemacht hat. Muss ja einen Grund haben.
    Also vielleicht sollte man ja generell einen DefaultValue festlegen.
    Könnte hier mal bitte jemand mit mehr als zwei Worten antworten?

    Edit zu 2:
    Die Methode scheint u.a. ja mein DataSet aus der xml zu füllen.
    Verwendest du hier den Pfad ..\..\DataStuff\AngelmarkenData.xml nur während der Erstellung des Programmes und änderst in dann später?
    Die (ich glaube durch SolutionExplorer kpoierte) Angelmarken.xml sieht folgendermaßen aus:
    <?xml version="1.0" encoding="utf-8" ?> <dtsAngelmarken xmlns="http://tempuri.org/StechuhrDts.xsd"> </dtsAngelmarken>
    handelt es sich hier um einen Fehler im SolutionExplorer?


    Und ich schaffe es nicht, das DataSet in die xml zu bringen.

    VB.NET-Quellcode

    1. Private Sub frmAngelmarken_Closed(sender As Object, e As EventArgs) Handles Me.Closed
    2. Save(dtsAngelmarken, Me, False)
    3. End Sub

    Auf welche Form muss ich hier verweisen, und warum?

    Also wie bekomme ich mein DataSet in xml?

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

    DerSmurf schrieb:

    Ja, das geht natürlich.
    Aber besser ist ja, den Grund herauszufinden, warum @ErfinderDesRades das rein gemacht hat. Muss ja einen Grund haben.
    Ja

    DerSmurf schrieb:

    Also vielleicht sollte man ja generell einen DefaultValue festlegen.
    Ja

    DerSmurf schrieb:

    Könnte hier mal bitte jemand mit mehr als zwei Worten antworten?
    Nein.

    Naja, meinetwegen:
    Es ist ja höchst angeraten, immer AllowNull=False zu setzen, soweit es irgend geht, und bei Strings gehts immer.
    Andernfalls verkompliziert sich die Datenverarbeitung enorm, weil du bei jedem(!!!!) Abruf vorher mit einer Extra-Methode erstmal prüfen musst, ob der Wert überhaupt abgerufen werden kann.
    Also AllowNull=False ok?
    Wenn aber AllowNull=False, und du hast keinen Defaultwert, dann macht die DataTable bei neuen DataRows eben defaultmässig immer erstmal DbNull rein.
    Logisch, was sonst? hat ja kein Defaultwert.

    Dummerweise gibts dann aber 5 Zeilen weiter einen Fehler, weil AllowNull=False :S

    Übrigens kann man das alles (und noch mehr) hier nachlesen: codeproject.com/Articles/10309…l-Datamodel-for-Beginners und die beiden Folge-Artikel



    Wenn du dich ans von mir gegebene Template hältst, gehts so:

    VB.NET-Quellcode

    1. Dts.Save(me)

    DerSmurf schrieb:

    Auf welche Form muss ich hier verweisen, und warum?
    Das Form, wo du grad drauf bist, und von wo du speichern willst.
    Meist das MainForm.
    Das Form zu übergeben ist sinnvoll, wenn Eingaben nicht abgeschlossen sind - dann ruft die Save-Methode BindingSource.EndEdit auf. Und ausserdem Form.Validate - da kann man auch noch Wert-Gültigkeiten überprüfen, bevor sie gespeichert werden.
    Und noch einige andere Sachen - ach - es ertönt glaub noch ein "Plink!" als Feedback, wenn erfolgeich gespeichert wurde.

    Übrigens kannste die frmAngelmarken_Closed auch weglassen, wenn du das Dataset entsprechend registrierst:

    VB.NET-Quellcode

    1. Dts.DataFile("..\..\DataStuff\AngelmarkenData.xml").Register(Me, handleFormClosing:=True).Fill

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

    Vielen Dank für die Erklärung und den Link!

    Ich habe nun die Personenverwaltung, inklusive Speicherung, fertiggestellt.
    Deine Nachfrage ob gespeichert werden soll, habe ich aber erstmal auskommentiert.
    Das erscheint mir für diesen Verwendungszweck erstmal lästig. Aber kann ich ja wieder entkommentieren, wenn es hier ein Plus bringt, an das ich gerade nicht denke.

    Also die TabPage Personen ist dann (erstmal) fertig. Was haltet ihr davon?

    Und eine Frage wäre noch offen.

    DerSmurf schrieb:

    Verwendest du hier den Pfad ..\..\DataStuff\AngelmarkenData.xml nur während der Erstellung des Programmes und änderst in dann später?

    Also sonst wäre ja meine DataSet.xml zwei Ordner über der exe. Das wäre ja komisch.
    Dateien
    • Angelmarken00.zip

      (284,94 kB, 36 mal heruntergeladen, zuletzt: )

    ErfinderDesRades schrieb:

    ach - es ertönt glaub noch ein "Plink!

    Danke, ich hatte mich auf dem Firmen-PC schon gefragt, wo die dusseligen Sounds her kommen - bei mir daheim sind die Systemsounds ausgeschaltet :D
    Konnte ich damit dann auch mal rausnehmen :thumbup:

    Vorweg: bei mir ist die Solution nicht lauffähig - die Helpers sind nicht korrekt eingebunden - selbst wenn ich die Verweise auf
    GeneralHelpers und WinFormHelpers aktualisiere erhalte ich fehler:



    @DerSmurf:
    Ich hab deine KeyPress mal in KeyDown zusammengefasst:

    VB.NET-Quellcode

    1. Private Sub frmAngelmarken_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
    2. If e.KeyCode = Keys.K AndAlso e.Modifiers = Keys.Control Then
    3. If TCMain.SelectedTab Is TPPersons Then PersonCopy()
    4. e.SuppressKeyPress = True
    5. End If
    6. If Me.TBPersonSearch.Focused Then
    7. e.SuppressKeyPress = True
    8. End If
    9. Select Case e.KeyCode
    10. Case Keys.Escape : If TCMain.SelectedTab Is TPPersons Then DelPersonSearch()
    11. Case Keys.Delete : If TCMain.SelectedTab Is TPPersons Then PersonDelete()
    12. Case Keys.Back
    13. If TCMain.SelectedTab Is TPPersons Then
    14. If TBPersonSearch.Text.Length > 0 Then TBPersonSearch.Text = TBPersonSearch.Text.Substring(0, TBPersonSearch.Text.Length - 1)
    15. End If
    16. e.SuppressKeyPress = True
    17. End Select
    18. End Sub


    Das hier kann ich mir nicht erklären - sollte doch automatisch passieren, wenn die Textbox selektiert ist oder?

    VB.NET-Quellcode

    1. Private Sub frmAngelmarken_KeyPress(sender As Object, e As KeyPressEventArgs) Handles MyBase.KeyPress
    2. 'Tasten in TB übergeben
    3. If TCMain.SelectedTab Is TPPersons Then TBPersonSearch.AppendText(e.KeyChar)
    4. End Sub



    BindingSource.FilterX kannste wie folgt nutzen:
    PersonBindingSource.FilterX("Name LIKE *?* OR Vorname LIKE *?*", TBPersonSearch.Text, TBPersonSearch.Text)


    Statt Exit Sub nimmst du Return


    Statt PersonBindingSource.RemoveCurrent() müsste glaub sinnvollerweise die Row gelöscht werden: Person.Delete


    Statt PersonBindingSource würde ich die Bs wie folgt benamen: bsPerson
    @ErfinderDesRades: Ich vermisse hier die BindingSource.At(Of TypedRow)-Extension - hattest du die nicht mehr in den Helpers?
    Und warum geht eigentlich sowas nicht?:

    VB.NET-Quellcode

    1. Dim rwOriginal = bsPerson.At(Of PersonRow)
    2. Dim rwKopie = dts.Person.AddPersonRow(rwOriginal)

    also das addpersonrow(rwOriginal) geht, aber Dim rwKopie mit Erstellen der Kopie (damit ich die neue Row direkt griffbereit hätte) geht leider nicht..


    Deine Tuple-Methode zum Kopieren einer Person versteh' ich nicht.. das wird sicher mit einer
    dtsAngelmarken.Person.AddPersonRow(SelectedPerson) gehen, die dann rausfinden und editieren...


    Jo, so in etwa sähe bei mir der Code auf frmAngelmarken aus:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.ComponentModel, System.Drawing, System.Windows.Forms
    2. Imports Angelmarken.dtsAngelmarken
    3. Public Class frmAngelmarken
    4. #Region "Form"
    5. Public Sub New()
    6. InitializeComponent()
    7. Me.Text = Date.Now.ToString
    8. If NotifyPropertyChanged.IsInDesignMode Then Return
    9. ControlStyling.StyleControls(Me)
    10. Dts.DataFile("..\..\DataStuff\AngelmarkenData.xml").Register(Me, True).Fill
    11. End Sub
    12. Private Sub frmAngelmarken_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    13. 'verstecken der Reiter vom Main TabControl
    14. With TCMain
    15. .SuspendLayout()
    16. .SizeMode = TabSizeMode.Fixed
    17. .ItemSize = New Size(0, 1)
    18. .Appearance = TabAppearance.Buttons
    19. .ResumeLayout()
    20. End With
    21. End Sub
    22. Private Sub frmAngelmarken_Closed(sender As Object, e As EventArgs) Handles Me.Closed
    23. Dts.Save(Me, True)
    24. End Sub
    25. Private Sub frmAngelmarken_KeyPress(sender As Object, e As KeyPressEventArgs) Handles MyBase.KeyPress
    26. 'Tasten in TB übergeben
    27. If TCMain.SelectedTab Is TPPersons Then TBPersonSearch.AppendText(e.KeyChar)
    28. End Sub
    29. Private Sub frmAngelmarken_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
    30. If e.KeyCode = Keys.K AndAlso e.Modifiers = Keys.Control Then
    31. If TCMain.SelectedTab Is TPPersons Then PersonCopy()
    32. e.SuppressKeyPress = True
    33. End If
    34. If Me.TBPersonSearch.Focused Then
    35. e.SuppressKeyPress = True
    36. End If
    37. Select Case e.KeyCode
    38. Case Keys.Escape : If TCMain.SelectedTab Is TPPersons Then DelPersonSearch()
    39. Case Keys.Delete : If TCMain.SelectedTab Is TPPersons Then PersonDelete()
    40. Case Keys.Back
    41. If TCMain.SelectedTab Is TPPersons Then
    42. If TBPersonSearch.Text.Length > 0 Then TBPersonSearch.Text = TBPersonSearch.Text.Substring(0, TBPersonSearch.Text.Length - 1)
    43. End If
    44. e.SuppressKeyPress = True
    45. End Select
    46. End Sub
    47. #End Region 'Form
    48. #Region "Clickables"
    49. Private Sub btn_Click(sender As Object, e As EventArgs) Handles BTNHome.Click,
    50. BTNNewSale.Click,
    51. BTNPersonCopy.Click,
    52. BTNPersonDelete.Click,
    53. BTNPersonDelSearch.Click,
    54. BTNPersonEdit.Click,
    55. BTNPersonNew.Click,
    56. BTNPersons.Click,
    57. BTNSettings.Click
    58. Select Case True
    59. Case sender Is BTNHome : Me.TCMain.SelectedTab = TPHome
    60. Case sender Is BTNNewSale : Me.TCMain.SelectedTab = TPSale
    61. Case sender Is BTNPersonCopy : PersonCopy()
    62. Case sender Is BTNPersonDelete : PersonDelete()
    63. Case sender Is BTNPersonDelSearch : DelPersonSearch()
    64. Case sender Is BTNPersonEdit : PersonEdit()
    65. Case sender Is BTNPersonNew : bsPerson.EditNew(Of frmEditPerson)
    66. Case sender Is BTNPersons : Me.TCMain.SelectedTab = TPPersons
    67. Case sender Is BTNSettings : Me.TCMain.SelectedTab = TPSettings
    68. End Select
    69. End Sub
    70. #End Region 'Clickables
    71. #Region "Tab Page Personen"
    72. Private Sub PersonEdit()
    73. bsPerson.EditCurrent(Of frmEditPerson)
    74. End Sub
    75. Private Sub PersonCopy()
    76. 'Daten der aktuell ausgewählten Person auslesen
    77. If bsPerson.Current Is Nothing Then Return
    78. Dim selectedPerson = bsPerson.At(Of PersonRow)
    79. dtsAngelmarken.Person.AddPersonRow(SelectedPerson)
    80. 'neue Row abfangen und an Edit-Dialog übergeben
    81. End Sub
    82. Private Sub PersonDelete()
    83. If bsPerson.Current Is Nothing Then Return
    84. 'ausgewählten Person auslesen
    85. Dim selectedPerson = bsPerson.At(Of PersonRow)
    86. If MessageBox.Show(Person.Vorname & " " & Person.Name & " und all seine Einkäufe werden gelöscht. " & Environment.NewLine &
    87. "Sind sie sicher?", "Person löschen", MessageBoxButtons.YesNo) = DialogResult.Yes Then
    88. selectedPerson.Delete()
    89. End If
    90. End Sub
    91. Private Sub DelPersonSearch()
    92. TBPersonSearch.Text = ""
    93. End Sub
    94. 'Filter für Personbindingsource (Suchen Textbox)
    95. Private Sub TBPersonSearch_TextChanged(sender As Object, e As EventArgs) Handles TBPersonSearch.TextChanged
    96. bsPerson.FilterX("Name LIKE *?* OR Vorname LIKE *?*", TBPersonSearch.Text, TBPersonSearch.Text)
    97. End Sub
    98. #End Region
    99. End Class

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

    Dieser Beitrag wurde bereits 9 mal editiert, zuletzt von „tragl“ ()

    Bin jetzt am Handy und lese @ErfinderDesRades Beiträge auf Codeproject, daher erstmal nur die Reaktion auf die Lauffähigkeit.
    Den gleichen Fehler bekomme ich auch (auch in der Vorlage, die ich kopiert habe), wenn ich die gesamte Projektmappe erstelle.
    Jedes Projekt einzeln erstellen, klappt aber wunderbar. Deswegen hab ich gedacht, dass die beiden Helper Projekt aufeinander zugreifen und deswegen ein erstellen des einen, ohne den anderen nicht möglich ist (Was ja beim kompilieren der gesamten Mappe passiert)
    Hab ich falsch gedacht und immernoch ein Problem durch die Vorlage?

    DerSmurf schrieb:

    Hab ich falsch gedacht und immernoch ein Problem durch die Vorlage?

    jo, keine Ahnung - ist wohl eine neuere Version der Helpers als meine. Ich nutz alle Helpers in einem Separaten Helpers-Projekt und binde das in meine Projekte ein, damit läuft alles..

    Edit: zur größten Not musst du Bescheid sagen, dann schick' ich dir meine Helpers rüber - könnten auch ne Teamviewer-Sitzung machen und das einmal einbauen, kann mir die Fehler grad nicht erklären.
    Aber mal warten was Edr dazu sagt

    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Anbei mal meine Version.
    Wie gesagt: nur die Verweise auf die eingebundenen Projekte erneuert.
    Und kann sein, dass ich auch Framework-Versionen aller Projekte angeglichen hab - eine Solution läuft auch dann nicht, wenn die Helpers eine höhere Version haben als die Haupt_Anwendung.
    Warum Projekte einzeln kompilieren, gemeinsam aber nicht ist mir nicht nachvollziehbar.
    In meiner Welt muss eine Solution nach Nuget_restaurieren, dann Menü-Erstellen-Alles_Bereinigen, und dann Menü-Erstellen-Alles_Compilieren, laufen.
    Dateien
    • Angelmarken00.zip

      (284,95 kB, 37 mal heruntergeladen, zuletzt: )
    Ja sehr schön.
    Deine Solution läuft jetzt auch bei mir ohne Probleme.
    Ich habe mir hieraus erstmal ein neues Template gebastelt, weil das werde ich ja später bestimmt noch brauchen.
    Wenn ich das Template nun kopiere, kann ich die neue Solution auch ohne Probleme (also Gesamte Projektmappe kompilieren) laufen lassen :o)

    So. Kommen wir zum Code.
    1. KeyPress / Down:
    Spoiler anzeigen
    Sinn und Zweck dieser Subs ist u.a. dass der User die Textbox nicht seleltieren muss um zu suchen.
    Da es ja eh nur diese eine Stelle gibt, wo ich auf der Form was hinschreiben kann, fände ich ein selektieren lästig.

    tragl schrieb:

    Das hier kann ich mir nicht erklären - sollte doch automatisch passieren, wenn die Textbox selektiert ist oder?
    VB.NET-Quellcode
    Private Sub frmAngelmarken_KeyPress(sender As Object, e As KeyPressEventArgs) Handles MyBase.KeyPress
    'Tasten in TB übergeben
    If TCMain.SelectedTab Is TPPersons Then TBPersonSearch.AppendText(e.KeyChar)
    End Sub

    Das sorgt eben dafür, dass das geht.
    Dementsprechend breche ich die Sub ab, wenn die Textbox selektiert ist (damit die Eingabe nicht doppelt erscheint).

    VB.NET-Quellcode

    1. 'abbrechen, wenn eine Textbox ausgewählt
    2. If Me.TBPersonSearch.Focused Then Exit Sub

    Mein Problem mit dieser Methode im Keydown ist, dass jede Taste in der Textbox erscheint, also z.B. auch STRG. Hier würde ich nämlich:

    VB.NET-Quellcode

    1. If TCMain.SelectedTab Is TPPersons Then TBPersonSearch.AppendText(e.KeyCode.ToString)

    verwenden um dass zu erreichen. Aber vielleicht gehts ja anders, oder vlt. alles zusammen im Keypress, damit ich eine der beiden Subs entfernen kann.
    Ich bekomme nur die Entf Taste im Keypress irgendwie nicht abgefangen (dann könnte ich ja KeyDown entfernen):

    VB.NET-Quellcode

    1. If e.KeyChar = Convert.ToChar(Keys.Delete) Then
    2. If TCMain.SelectedTab Is TPPersons Then PersonDelete()
    3. End If[/spoiler][spoiler]

    da passiert nüscht. Wenn ich einen Haltepunkt im Keypress setze und die Entf Taste drücke, passiert nix - ich lande nicht im Code.
    Mit deiner Keydown Methode, ist übrigens keine Verwendung der Tastatur mehr möglich.


    2.PersonBindingSource.FilterX hab ich geändert.

    3.

    tragl schrieb:

    Statt Exit Sub nimmst du Return

    Hab ich an allen Stellen geändert. Warum ist Return besser, wo ist der Unterschied? Nehme ich immer Return statt Exit Sub?

    4.

    tragl schrieb:

    Statt PersonBindingSource würde ich die Bs wie folgt benamen: bsPerson

    Jo, hab ich gestern Abend in einem von EdRs codeproject Blogs gelesen und entsprechend geändert (Hier weiß ich dann ausnahmsweise mal warum ich das tun sollte :o)

    5.

    tragl schrieb:

    Statt PersonBindingSource.RemoveCurrent() müsste glaub sinnvollerweise die Row gelöscht werden: Person.Delete

    Der Objektkatalog sagt zu BindingSource.RemoveCurrent : "Entfernt das aktuelle Element aus der Liste." - genau das will ich doch?

    6.

    tragl schrieb:

    Deine Tuple-Methode zum Kopieren einer Person versteh' ich nicht.. das wird sicher mit einer
    dtsAngelmarken.Person.AddPersonRow(SelectedPerson) gehen, die dann rausfinden und editieren...

    Das Problem hatte ich mal mit einem anderen Programm (und angehängten HelpersSmallEd). Da hat mir EdR diese Tuple Methode erklärt.
    Ich weiß nicht, ob es mit den "großen" Helpers anders geht. Aber da wird sich @ErfinderDesRades bestimmt einmischen

    7. Ich lade die Solution hier mal neu hoch.
    Das Programm ließ sich (vor dem kopieren mit Solution Explorer) bei mir fehlerfrei kompilieren.
    Wenn ich die Angelmarken.sln mit dem SolutionExplorer öffne und auf "BackupZip" klicke, und dann die Solution öffne, die sich im Ordner "BackZip" befindet öffne, erhalte ich beim kompileiren folgenden Fehler:
    1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(2182,5): warning MSB3245: Dieser Verweis konnte nicht aufgelöst werden. Die "Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"-Assembly wurde nicht gefunden. Stellen Sie sicher, dass die Assembly auf dem Datenträger vorhanden ist. Falls dieser Verweis im Code erforderlich ist, können Kompilierungsfehler auftreten.
    Es lässt sich aber alle kompilieren.
    Die GeneralHelpers verweisen jetzt aber auf eine Newtonsoft.Json. Bei Pfad ist angegeben, dass die Referenz nicht gefunden werden kann.
    Das betrifft jetzt aber nicht nur die kopierte Solution, sondern im Original taucht die gleiche Warnung (und der gleiche falsche Verweis) auf.
    Also wurde durch die SolutionExplorer Kopie die Original Helpers verändert.
    Wenn ich den Verweis auf die Newtonsoft.Json entfernte, läuft alles wieder.
    Nachdem ich diesen Verweis jetzt entfernt habe, ist er beim erneuten kopieren auch nicht wieder aufgetaucht.
    Also die Solution im Anhang läuft bei mir anstandslos (das Main Projekt auch).
    Ist hier in meinem VS was falsch eingestellt, mach im Solution Explorer was falsch? Was ist hier los?
    Dateien
    • Angelmarken00.zip

      (284,79 kB, 45 mal heruntergeladen, zuletzt: )

    DerSmurf schrieb:

    Was ist hier los?

    Newtonsoft.Json ist eine dll, die über Nuget bezogen wird.
    Ich dachte, ich hätte die Nuget-Abhängigkeit aus den Helpers entfernt.
    Übrigens ists ja nur ein Warning, kein Fehler.

    PS: Bei dem, was du geuppt hast, ist auch alles sauber.



    Das mit den Tuples scheint mir ganz korrekt so.
    Bedient eine Überladung der .EditNew()-Extension, wenn man eine Vorbelegung im neuen Datensatz haben will.
    Ist umständlich - kann man vlt. besser machen. Aber ich wollte mir für diese Sonderlocke nicht das Hirn kaputt-denken.

    Tatsächlich ist mit meine Helpers sogar eine recht kompakte Syntax möglich:

    VB.NET-Quellcode

    1. 'statt
    2. With dtsAngelmarken.Person
    3. Dim tpls As New List(Of Tuple(Of DataColumn, Object))
    4. tpls.Add(Tuple.Create(Of DataColumn, Object)(.NameColumn, SelectedPerson.Name))
    5. tpls.Add(Tuple.Create(Of DataColumn, Object)(.StrasseColumn, SelectedPerson.Strasse))
    6. tpls.Add(Tuple.Create(Of DataColumn, Object)(.HausnummerColumn, SelectedPerson.Hausnummer))
    7. tpls.Add(Tuple.Create(Of DataColumn, Object)(.PLZColumn, SelectedPerson.PLZ))
    8. tpls.Add(Tuple.Create(Of DataColumn, Object)(.OrtColumn, SelectedPerson.Ort))
    9. BSPerson.EditNew(Of frmEditPerson)(tpls)
    10. End With
    11. ' so:
    12. With dtsAngelmarken.Person
    13. Dim tplss = TupleList.From(Of DataColumn, Object)(.NameColumn, SelectedPerson.Name)(.StrasseColumn, SelectedPerson.Strasse) _
    14. (.HausnummerColumn, SelectedPerson.Hausnummer)(.PLZColumn, SelectedPerson.PLZ)(.OrtColumn, SelectedPerson.Ort)
    15. BSPerson.EditNew(Of frmEditPerson)(tpls)
    16. End With




    Nehme ich immer Return statt Exit Sub?
    Es ist kein Unterschied.
    Nur die allermeisten Coder mögen Exit Sub nicht. Und Exit Function auch nicht.
    Ist auch nicht so richtig wirklich ganz nachvollziehbar, warum es für dasselbe zwei verschiedene Syntaxe geben muss.



    Der Objektkatalog sagt zu BindingSource.RemoveCurrent : "Entfernt das aktuelle Element aus der Liste." - genau das will ich doch?
    Musst du aufpassen, ob du das willst.
    .Remove entfernt den Datensatz, trägt aber nix in die Änderungsverfolgung ein.
    Falls die Änderung auf eine Datenbank soll geht das nur mit .Delete.
    Solange nur eine .xml bespielt wird ist egal, weil weg ist weg.
    Achso - ein Unterschied besteht auch bei DatasetOnly, nämlich Löschweitergabe: die wird auch nur durch .Delete umgesetzt.

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

    Ich werde mich das nächste mal etwas mehr in Geduld üben :o)

    ErfinderDesRades schrieb:

    .Remove entfernt den Datensatz, trägt aber nix in die Änderungsverfolgung ein.
    Falls die Änderung auf eine Datenbank soll geht das nur mit .Delete.

    Wenns für die xml egal ist, ists wohl besser, ich gewöhne mir .Delete an.
    Dann gibts wohl später keine Hudeleien, wenn ich mal eine DB anbinden sollte.
    @DerSmurf:
    Lad nochmal eine laufende Solution hoch, dann guck' ich mir mal das mit den Key-Events an und bastel' dir ggf.
    noch die ein oder anderen nützlichen Helpers (Bsp. Bindingsource.At(Of TypedRow) etc. rein.
    Kann mich da morgen abend drum kümmern.

    LG
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Huhu
    Der Upload in Post 71 ist aktuell. Den kannst du nehmen.-
    Das einzige was hier noch nicht geändert ist, die die vereinfachte Schreibweise der Tuplesübergabe in Bs.EditNew(of ...) und ich lösche hier noch mit BS.removecurrent.
    Alle anderen Änderungen sind umgesetzt.
    Da mein Code ja soweit ohne "Mängel" zu sein scheint, bis auf die Verwendungung von KeyPress und KeyDown, was ich aber ja noch später beheben kann und was keinen Einfluss auf den weiteren Code hat, mache ich über Pfingsten die Einstellungen fertig.
    Also eine GUI für das Anlegen von Lieferanten, Angelmarken (Artikeln), usw.
    Hier muss ich aber glaube ich vorher meine DataTable "Marke" noch verändern.
    Es werden dort folgende Marken gespeichert:

    1. Gruppe
    Fischereiabgabe Erwachsen 1 Jahr - 12 Euro
    Fischereiabgabe Erwachsen 5 Jahre - 40 Euro
    Fischereiabgabemarke Kinder 1 Jahr - 2,50 Euro
    Ausweis für Fischereiabgabemarke (dort werden eben die Marken eingeklebt)
    Die Preise sind immer gleich, egal wann gekauft wird.

    2. Gruppe
    DAV Erwachsen 1 Jahr - 73 Euro
    DAV Jugendliche 1 Jahr - 20 Euro
    Ausweis für DAV Marken - 1 Euro
    Hier sind aber eben die Preise nicht immer gleich:
    Neue Mitglieder (egal ob Erwachsen oder Jugend) zahlen 5 Euro Aufnahme - Neu ist, wer im vergangenen Jahr keine Marke gekauft hat
    Verzug (ab dem 01.04.) 5 Euro - wer also seine Marke nach diesem Datum kauft zahlt 5 Euro
    Es wird aber nur Verzug ODER neues Mitglied berechnet. Also nur einmal 5 Euro aufgeschlagen.

    3.Gruppe
    Mecklenburg Karte - 10,50 Euro
    Sachsen Anhalt Karte - 10,50 Euro
    Hier sind die Preise auch immer gleich - verkauf erfolgt aber nur, wenn Kunde Fischereischein hat.

    Für Gruppe 1 und 3 passt meine DataTable Marke ja.
    Damit auch Gruppe 2 sonnvoll gespeichert werden kann, würde ich folgende Änderungen an der Table vornhemen:
    Eine AllowNull Spalte "Verzugsdatum" - um zu speichern ab wann Verzug fällig ist. Mit IsMarke.VerzugsdatumNull kann ich abfragen ob überhaupt Verzug anfällt.
    Decimal Spalte Verzugsgebühren - um zu speichern wie hoch der Verzug ist
    Booleanspalte Neuanmeldung - True = Extrakosten für neue Mitglieder
    Decimal Spalte Neuanmeldungsgebühren - um zu speichern wie hoch die Anmeldegebühren sind
    Boolean Fischereischein nötig: brauche ich aktuell nur bei Sachsen Anhalt und MV. Aber wenn so kann ich das im DataSet hinterlegen und muss später nichts im Code ändern, falls man z.B. für DAV Marken auch einen Fischereischein benötigt. Oder ich mal neue Marken bekomme, die ich noch nicht habe.

    Macht das für euch so Sinn, wie ich das vorhabe?
    Bilder
    • DataSet.png

      155,13 kB, 1.321×786, 36 mal angesehen
    Ich würde Marken mit Verzug als eigene Artikel einstellen.
    Da dynamisch abhängig vom Heute-Datum automatisch einen Preisaufschlag berechnen - der ja per DataRelation in EinkaufPosition eingehen muss - da müsste man schon bisserl tricksen, indem man bei Programmstart codeseitig geeignete berechnete Spalten einträgt ins Dataset.
    Hmm - wird auch schwierig mit Lieferung und Abrechnung.

    Neues Konzept: Aufschläge jeder Art sind besondere Artikel, und werden beim Einkauf als Extra-Einkauf-Positionen zugefügt.
    So wie im Supermarkt der FlaschenPfand eine Extra-Position auffm Bon ist.

    DerSmurf schrieb:

    Eine AllowNull Spalte "Verzugsdatum" - um zu speichern ab wann Verzug fällig ist

    und hier würd' ich nicht mit AllowNull arbeiten, sondern mit einem besonderen "Default-Datum", was du abbprüfen kannst /z.B. 01.01.1900
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup: