Bitte um Bewertung meines zweiten Projektes - Tea Timer

    • Release
    • Open Source

    Es gibt 68 Antworten in diesem Thema. Der letzte Beitrag () ist von petaod.

      Nabend.
      Ich habe die aktuelle Version hier angehangen.
      Eins vorab zur Einstellungenform, hier müssen noch die Datagridviews bearbeitet werden und eine validierung rein, damit keine falschen Werte eingegeben werden können.
      Habe die Gridviews nur erstmal dahingeschmissen, damit ich mein DataSet befüllen kann.
      Habe nun zwei Gefäße erstellt - Das Minutengefäß, hier gibt es nur Abkühlzeiten in Minuten und entsprechend ein Sekundengefäß.
      So lässt sich mit einem Blick überprüfen, ob die korrekte Abkühlzeit dargestellt wird.

      Das Progamm läuft, aber es gibt noch "unschönheiten"
      1. Wenn du einen Tee aus dem Datagridview auswählst und dannach das Gefäß änderst, ist zu sehen, dass das Label "lblTemperatur" für einen kurzen Moment 100° anzeigt, und erst dann auf den korrekten Wert springt und wahrscheinlich damit zusammenhängend das folgende:
      2. ich habe das Gefühl, dass eine Optimierung meines DataSets von nöten ist und mir Code ersparen würde.
      Ich habe versucht im DataSet eine Beziehung zwischen der Temperaturspalte aus "DTTeesorten" mit der Spalte "ID" aus Abkuelzeiten herzustellen.
      Der Gedanke war, dass dadurch eine indirekte Beziehung zur Gefaess Tabelle entsteht und die Abkühlzeit automatisch (also ohne Code - nur durchs Binding) angezeigt wird.
      Klapp aber nicht :( Wo ist denn hier mein Denkfehler?
      3. Das Label "lblName" (unter dem Label "Ziehzeit") zeigt beim Programmstart immer den Namen des ersten Tees aus dem DataSet. Kann ich dies trotz Binding unterbinden, oder hilft hier nur ein Entfernen des Bindings und setzen des Labeltextes per Code, oder eben eine Auswahl eines Wertes im Teesorten Datagridview per Code
      Dateien
      • Tea Timer.zip

        (1,95 MB, 14 mal heruntergeladen, zuletzt: )
      Mir raucht langsam etwas der Kopf. Wahrscheinlich hast Du es schon erklärt, aber ich habe mal wieder den Faden verloren.
      Was hat es mit der Tabelle DTTeesorten auf sich bzgl. Temperatur, Minuten und Sekunden? Was sind das für Angaben? Ok, Temperatur wahrscheinlich: Der Tee darf maximal dieser Temperatur ausgesetzt werden. Aber was ist dann die Zeit? Ziehzeit? Oder doch nur die Abkühlzeit, die das Wasser für diesen Tee braucht, um auf die Solltemperatur zu kommen?
      Beide Punkte wären momentan inkonsistent eingepflegt. Wäre es die Ziehzeit, würde sich bei Teeauswähl nicht die 1. Zeile im Hauptformular bzgl. der Zeit ändern, sondern die 2. Zeile (Ziehzeit). Wäre es die Abkühlzeit, wäre es Datenredundanz, da dies ja schon durch die anderen beiden DataTables abgedeckt ist.

      Man wählt einen Tee aus. Für den muss das Wasser von 100 °C auf eine bestimmte Temperatur gebracht werden. Das dauert eine gewisse Zeit, also die Abkühlzeit.
      Warum kann man trotzdem im Hauptformular in der 1. Zeile (Temperatur) eine Temperatur/Zeitkombination angeben? Wenn ein Touareg mit 90 °C und 2 Minuten eingestellt ist, warum sollte man daran noch was verändern können? Und warum ist der andere Tee ebenfalls mit 2 Minuten versehen, aber nur mit 70 °C?
      Warum ist bei 100 °C die Zeit 1 Minute?

      Vielleicht kann ich Dir besser helfen, wenn Du diese Fragen erstmal beantwortest.
      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.
      Alles gut.
      Hier deine Antworten
      1.
      ]Was hat es mit der Tabelle DTTeesorten auf sich bzgl. Temperatur, Minuten und Sekunden?

      Temperatur: die Wassertemperatur, bei der der Tee reinkommt. Also 90° bedeutet, dass der Tee mit 90° warmen Wasser aufgegeossen wird.
      Die Zeit ist die Zeit, die der Tee dann zum ziehen benötigt.
      2.
      Beide Punkte wären momentan inkonsistent eingepflegt. Wäre es die Ziehzeit, würde sich bei Teeauswähl nicht die 1. Zeile im Hauptformular bzgl. der Zeit ändern, sondern die 2. Zeile (Ziehzeit)

      es ändert sich ja aber auch die Ziehzeit entsprechend, so wie sie es soll. Hier gibt es ja ein entsprechendes Binding.
      3-
      Wenn ein Touareg mit 90 °C und 2 Minuten eingestellt ist, warum sollte man daran noch was verändern können?

      Das dient dazu, dass ich nicht jeden Tee einpflegen muss, sondern nur Tees de ich oft trinke speichern möchte.
      Also sagen wir ich bestelle eine handvoll Tee und bekomme Proben zum Beispiel. Dann muss ich nicht die Proben (die meist eh nur eine Tasse sind) erst einpflegen und dann wieder löschen.
      4.
      Warum ist bei 100 °C die Zeit 1 Minute?

      Das ist natürlich sinnbefreit (wie die kompletten Abkühlzeiten in der aktuellen Version), jedoch fand ich es mit den aktuell eingestellten Abkühlzeiten einfacher nachzuvollziehen, was da gerade ausgewählt ist, als mit sinnvollen Werten.
      Deshalb "Minutengefäß: 100° 1min / 90° 2min / 80° 3min / 70°4min / 60° 5min
      "Sekundengefäß - das gleiche in Sekunden
      So sieht man auf einen Blick, ob das Binding funktioniert.

      Also zur Übersicht:
      DTTeesorten speichert: Name des Tees / Temperatur, bei dem er aufgegossen wird / und die Ziehzeit
      Abkuehlzeten speichert: Temperatur nur 100 - 60° sollen später möglich sein) die Wassertemperatur zum aufgießen / und die Zeit die das Wasser braucht um auf diese Temperatur abzukühlen.

      Und der Sinn hinter dem Projekt am Beispiel Le Touareg (90° / 2 min Ziehzeit)
      Bisher koche ich Wasser, gieße es in mein Gefäß und stelle den Windows Timer auf 5min entspricht in meinem Standartgefäß dann ca. 90°)
      Ist der Timer durch kommt mein Tee ins Wasser und der Timer wird auf 2 min eingestellt, die Ziehzeit.
      Nach Ablauf dieses Timers ist der Tee dann fertig.
      Mein Programm vereint quasi beide Timer und erspart mir das ständige hin und herstellen und ermöglcht mir eben auch das speichern der Zeit, bis mein Wasser die entsprechende Temperatur hat (jetzt ja auch mit verschiedenen Gefäßen) - ich brauche also nur einmal Wasser kochen und mit Thermometer abkühlen lassen.
      Die Werte speicher ich und brauche nie wieder Wassertemperatur messen (oder in meine Textdatei schauen, wie lange das Wasser zum abkühlen auf die entsprechende Temperatur braucht)

      Dann kommt das Datagridview dazu, damit ich hier die Namen meiner Lieblingstees speichern kann (bisher auch in einer Textdatei), damit ich leichter neu bestellen kann.
      Damit ich dort aber nur Tee speichere, den ich auch trinke, gibt es die Buttons zum erhöhen / verringern von Ziehzeit und Temperatur.

      Edit:
      Ich habe das ganze mal Bildlich dargestellt.
      Bilder
      • Anmerkung 2019-05-14 091045.jpg

        255,65 kB, 2.060×1.314, 36 mal angesehen

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

      Bin gerade viel unterwegs, daher eine erste schnelle Lösung: Leider kann ich keinen Codeupload machen, aber zumindest ein Foto. Im DTTeesortenBindingSource_CurrentChanged-EventHandler und im gleichen für Abkuehlzeiten-BS nur reinschreiben: ChangeSettings()
      Und was ist ChangeSettings? Das, was Du schon als Kommentar reingeschrieben hast. Nämlich einfach nur das, was Du schon als Doppelcode hast, also von Dim aktuelleTeesorte = DirectCast... bis zur For-Schleife mit BS-Positionssetzung.
      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.
      Huhu
      Das verstehe ich nicht. Ich gehe mal davon aus du hast das getestet. Aber bei mir läuft der Code nicht.
      Wobei ich auch nicht verstehe, wo da jetzt der Unterschied ist.
      Letztendlich verschiebe ich ja nur den entsprechenden Code vom Datagridvie_CellClick ins Binding Source CurrentChanged Event, der DTTeesorten, bzw. Gefäßbindingsource.
      Das wirft mir allerdings eine Null Exception, beim ersten Cast der GefaessbindingSource.Current, raus.

      Aber wieso sollte das Verhalten meines Programmes mit deinem Vorschlag anders sein?
      Ein NullReference-Test ist immer sinnvoll als erste Zeile. Ich werd später noch als Nachbearbeitung den Code posten, mit dem es bei mir gut lief. Bin nur gerade am Handy und die Codeübertragung von meinem Pad klappt gerade nicht.

      ##########

      @DerSmurf: here we go:

      VB.NET-Quellcode

      1. Private Sub DTTeesortenBindingSource_CurrentChanged(sender As Object, e As EventArgs) Handles DTTeesortenBindingSource.CurrentChanged
      2. ChangeSettings()
      3. End Sub
      4. Private Sub AbkuehlzeitenBindingSource_CurrentChanged(sender As Object, e As EventArgs) Handles AbkuehlzeitenBindingSource.CurrentChanged
      5. ChangeSettings()
      6. End Sub
      7. Private Sub ChangeSettings()
      8. If GefaessBindingSource.Current Is Nothing Then Exit Sub
      9. Dim aktuelleTeesorte = DirectCast(DirectCast(DTTeesortenBindingSource.Current, DataRowView).Row, DTTeesortenRow)
      10. Dim aktuellesGefaess = DirectCast(DirectCast(GefaessBindingSource.Current, DataRowView).Row, GefaessRow)
      11. Dim AktuelleAbkuehlzeit = aktuellesGefaess.GetAbkuehlzeitenRows().FirstOrDefault(Function(x) x.Temperatur = aktuelleTeesorte.Temperatur)
      12. If AktuelleAbkuehlzeit Is Nothing Then
      13. MessageBox.Show($"Uh oh, die Abk�hlzeit f�r die Temperatur {aktuelleTeesorte.Temperatur} gibt's f�r das Gef�� {aktuellesGefaess.Name} gar nicht :-(")
      14. Exit Sub
      15. End If
      16. For i = 0 To Me.AbkuehlzeitenBindingSource.Count - 1
      17. Dim Abkuehlzeiten = DirectCast(DirectCast(AbkuehlzeitenBindingSource(i), DataRowView).Row, AbkuehlzeitenRow)
      18. If AktuelleAbkuehlzeit.Temperatur = Abkuehlzeiten.Temperatur Then
      19. AbkuehlzeitenBindingSource.Position = i
      20. Exit For
      21. End If
      22. Next
      23. End Sub
      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 1 mal editiert, zuletzt von „VaporiZed“ ()

      Ja alles gut.
      Mach dir keinen Stress.

      @VaporiZed
      Zu deinem Code.
      Krass, ich hätte gewettet, dass es keinen Unterschied macht, ob ich die Sub(s) nun im Datagridview Click Event, oder im BindingSource CurrentChanged Event laufen lasse.
      Aber ich halt die Schnauze :)

      Folgenden Code habe ich deinem hinzugefügt, damit die Ziehzeit noch angezeigt wird (Die Labels haben ja aktuell kein Binding):

      VB.NET-Quellcode

      1. ​ ZiehzeitSekunden = aktuelleTeesorte.Sekunden
      2. ZiehzeitMinuten = aktuelleTeesorte.Minuten
      3. lblZiehzeitMinuten.Text = ZiehzeitMinuten.ToString
      4. lblZiehzeitSekunden.Text = ZiehzeitSekunden.ToString


      Allerdings macht das AbkuehlzeitenbindingSource Change Event meine Temperatur Plus und Minus Buttons unbrauchbar, denn:

      VB.NET-Quellcode

      1. Private Sub btnTemperaturMinus_Click(sender As Object, e As EventArgs) Handles btnTemperaturMinus.Click
      2. AbkuehlzeitenBindingSource.MoveNext()
      3. End Sub
      4. Private Sub btnTemperaturPlus_Click(sender As Object, e As EventArgs) Handles btnTemperaturPlus.Click
      5. AbkuehlzeitenBindingSource.MovePrevious()
      6. End Sub

      in zusammenhang mit der Sub ChangeSettings() verhindert ja ein manuelles ändern.
      Ich würde nun eine Klassenweite Boolean (Namens Change) einbauen, die in den beiden oberen Subs True wird.
      Im AbkuehlzeitenBindingSouce Change Event prüfe ich dann

      VB.NET-Quellcode

      1. ​If Not Change then ChangeSettings()
      2. Change = False
      3. End if

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

      DerSmurf schrieb:

      Krass, ich hätte gewettet, dass es keinen Unterschied macht, ob ich die Sub(s) nun im Datagridview Click Event, oder im BindingSource CurrentChanged Event laufen lasse.
      Das sind einfach unterschiedliche Zeitpunkte, zu denen die Events ausgelöst werden. Und unter anderen Bedingungen. Aber das DGV_Cell(Content)Click sollte für sowas nie verwendet werden.
      Tja, das mit dem Boolean ist vielleicht etwas dirty, aber mir fällt auf Anhieb auch keine bessere Lösung ein. Leider. Von daher: Wenn es funktioniert, belass es dabei, bis es eine bessere Lösung gibt.
      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.
      Aber das DGV_Cell(Content)Click sollte für sowas nie verwendet werden.

      Ist gemerkt.

      So, nun habe ich einen Dirty Tea Timer, aber alles geht.
      Einzige Ausnahme macht eine Auswahl des Tees, anschließende Änderung der Temperatur und dann die Auswahl eines neuen Gefäßes.
      Jetzt springt die Temperatur natürlich wieder auf den Temperaturwert aus der Binding Source, aber das ist mir (mangels Idee) wurscht.

      Ich habe das Projekt hier nochmal hochgeladen, denn ich bekomme das DataSet nicht eingebunden.
      In Hauptform auf Einstellungen, und dort auf neu.
      In der sich jetzt öffnenden Form ist ein sinnloses Datagridview. Das kommt später weg, aber hiermit kann ich leichter prüfen, ob mein DataSet eingebunden ist.

      Achja edit:
      Deine Sub ChangeSettings() habe ich in irgendwas deutsches umbenannt, Teeaendern() oder sowas.
      In meinen zukünftigen Projekten wird sich nie wieder eine deutsche Bezeichnung finden, das nervt NAEMLICH ganz SCHOEN, aber im Tea Timer ist nunmal alles deutsch, außer der Name...
      Dateien
      • Tea Timer.zip

        (1,95 MB, 9 mal heruntergeladen, zuletzt: )
      Jou, wie in dem anderen Thread gedacht und erwähnt. Du musst auch das tDS immer weitergeben. Also in frmHautform statt

      VB.NET-Quellcode

      1. Private Sub EinstellungenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles EinstellungenToolStripMenuItem.Click
      2. Dim frmEinstellungen As New frmEinstellungen
      3. frmEinstellungen.GefaessBindingSource.DataSource = Me.DataSet1
      4. frmEinstellungen.Show(Me)
      5. End Sub

      eben

      VB.NET-Quellcode

      1. Private Sub EinstellungenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles EinstellungenToolStripMenuItem.Click
      2. Dim frmEinstellungen As New frmEinstellungen
      3. frmEinstellungen.GefaessBindingSource.DataSource = Me.DataSet1
      4. frmEinstellungen.DataSet1 = Me.DataSet1
      5. frmEinstellungen.Show(Me)
      6. End Sub

      und in frmEinstellungen

      VB.NET-Quellcode

      1. Private Sub Btngefaessneu_Click(sender As Object, e As EventArgs) Handles btngefaessneu.Click
      2. Dim frmnGefaess As New frmneuesGefaess
      3. frmnGefaess.DataSet1 = Me.DataSet1
      4. frmnGefaess.GefaessBindingSource.DataSource = Me.DataSet1
      5. frmnGefaess.Show(Me)
      6. End Sub

      Und schon läuft's. Ansonsten würdest Du mit Deinem bestehenden Code aus frmEinstellungen ein leeres, frmEinstellungen-eigenes tDS an frmneuesGefaess weitergeben.

      Allerdings funktioniert das Abspeichern der Temperaturzeiten noch nicht für das neue Gefäß. Aber das ist ja erstmal zweitrangig.
      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.
      Huhu
      Jupps, so macht alles Sinn.
      Ich habe erstmal nur eine Funktion für neues Gefäß eingefügt, damit die Fehlerquote kleiner ist und ich erstmal das wesentliche (Zugriff auf Dataset) testen kann.
      Nun werde ich die restliche Funktionalität schreiben.

      Edit:
      @VaporiZed
      HAHA! Deine Hilfe war nicht umsonst.
      Den Code zum erzeugen eines neuen Gefäßes inklusive Abkühlzeiten, konnte ich wie ein auswendig gelerntes Gedicht niedertippen!

      VB.NET-Quellcode

      1. Private Sub Btnspeichern_Click(sender As Object, e As EventArgs) Handles btnspeichern.Click
      2. 'Neues efäß anlegen
      3. Dim neuesgefaess As DataSet1.GefaessRow
      4. neuesgefaess = DataSet1.Gefaess.NewGefaessRow()
      5. neuesgefaess.Name = txtName.Text
      6. DataSet1.Gefaess.Rows.Add(neuesgefaess)
      7. 'ID des neuen Gefäßes speichern
      8. Dim ID As Integer = neuesgefaess.ID
      9. Dim Zeitarray(3, 1) As Integer
      10. 'Abkühlzeiten aus Form laden
      11. Zeitarray(0, 0) = Convert.ToInt32(nud90min.Value)
      12. Zeitarray(0, 1) = Convert.ToInt32(nud90sek.Value)
      13. Zeitarray(1, 0) = Convert.ToInt32(nud80min.Value)
      14. Zeitarray(1, 1) = Convert.ToInt32(nud80sek.Value)
      15. Zeitarray(2, 0) = Convert.ToInt32(nud70min.Value)
      16. Zeitarray(2, 1) = Convert.ToInt32(nud70sek.Value)
      17. Zeitarray(3, 0) = Convert.ToInt32(nud60min.Value)
      18. Zeitarray(3, 1) = Convert.ToInt32(nud60sek.Value)
      19. 'TODO Validierung hinzufügen, wenn Abkühlzeit Minute = 0 / restliche vali = Designer
      20. 'Schleife zum anlegen von Abkühlzeiten Rows (90° 80° 70° 60°)
      21. Dim Index As Integer = 0
      22. Dim neueAbkuehlzeit As DataSet1.AbkuehlzeitenRow
      23. For i As Integer = 90 To 60 Step -10
      24. neueAbkuehlzeit = DataSet1.Abkuehlzeiten.NewAbkuehlzeitenRow()
      25. neueAbkuehlzeit.Temperatur = i
      26. For j As Integer = 0 To 1
      27. neueAbkuehlzeit.ZeitMin = Zeitarray(Index, 0)
      28. neueAbkuehlzeit.ZeitSek = Zeitarray(Index, 1)
      29. Next
      30. neueAbkuehlzeit.GefaessID = ID
      31. DataSet1.Abkuehlzeiten.Rows.Add(neueAbkuehlzeit)
      32. Index += 1
      33. Next
      34. Me.Close()
      35. End Sub


      Ich habe aber noch eine Verständnissfrage zum DataSet, die mir beim erstellen der Gefäßlöschensub gekommen ist.
      Denn:

      VB.NET-Quellcode

      1. GefaessBindingSource.RemoveCurrent()

      löscht nicht nur das Gefäß aus der Table Gefaess, sondern auch die dazugehörigen Abkühlzeiten aus der Table Abkuehlzeiten.
      Das finde ich super, denn das erspart mir das manuelle löschen, aber ich verstehe nicht, wieso das so ist.
      Denn die Unique Eigenschaft von GefaessID (die Spalte aus Abkühlzeiten TD, welche mit Gefäß TD verknüpft ist) steht auf False.

      Ich könnte also doch eine Abkühlzeit auch mehreren Gefäßen zuordnen (theoretisch - praktisch macht es das ganze ja komplizierter).
      Dann würden doch meine Abkühlzeiten mit Sicherheit nicht gelöscht, wenn ich eins dieser Gefäße lösche.

      Wie funktioniert diese Unterscheidung?

      Edit2:
      Jezt habe ich doch einen logischen Fehler eingebaut :(
      Über der Schleife - also als erstes - habe ich noch eine Row für 100° - mit 0 Minuten und 0 Sekunden (ohne Änderung der GUI) eingefügt.
      Die hab ich irgendwie vergessen.

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

      Fangen wir mal vorne an - bei einem Punkt, den Du nicht gefragt hast. Es gibt für typisierte DataRows mindestens 2 Konstruktoren. Du verwendest immer die Variante 1, die als erstes von IntelliSense angeboten wird:

      VB.NET-Quellcode

      1. Dim neuesgefaess As DataSet1.GefaessRow
      2. neuesgefaess = DataSet1.Gefaess.NewGefaessRow()
      3. neuesgefaess.Name = txtName.Text
      4. DataSet1.Gefaess.Rows.Add(neuesgefaess)

      Du weißt, dass es auch eine 2. Variante gibt?

      VB.NET-Quellcode

      1. DataSet1.Gefaess.AddGefaessRow(txtName.Text)

      Da gibst Du alle Parameter für diese neue Zeile an, in der Reihenfolge, wie Du die Spalten im tDS-Designer angelegt hast inkl. Werten entspr. den Spaltenwerttypen. Bei Gefäß ist es einfach, da nur der Name angegeben werden muss. Die ID wird automatisch vergeben.
      Bei Abkühlzeit wäre es:

      VB.NET-Quellcode

      1. DataSet1.Abkuehlzeiten.AddAbkuehlzeitenRow(Temperatur, ZeitInMinuten, ZeitInSekunden, ZugehörigeGefäßZeile)

      Aber das nur am Rande.

      Warum werden die gefäßspezifischen Abkühlzeiten gelöscht: Weil Du es (unbewusst?) im tDS-Designer eingestellt hast (Korrektur: es ist die default-Einstellung):

      Die Löschregeleinstellung Cascade besagt soviel wie: Wird eine DataTable-Zeile gelöscht, die untergeordnete Zeilen (z.B. in anderen Tabellen) hat, werden diese mitgelöscht, da diese Zeilen ohne die zu löschende Hauptzeile inhaltlich keinen Sinn ergeben. Eine Abkühlzeit ohne Gefäß ergibt in Deinem Projekt keinen Sinn. Daher ist die Einstellung richtig und die gefäßspezifischen Abkühlzeiten werden mit dem Gefäß mitgelöscht.

      DerSmurf schrieb:

      Ich könnte also doch eine Abkühlzeit auch mehreren Gefäßen zuordnen
      Nur, wenn Du mehrere Gefäß-IDs pro Abkühlzeit hinterlegst, also in mehreren Spalten.

      Deinen Edit2 verstehe ich nicht. Da weiß ich nicht, wo Du gedanklich bist.
      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.
      Danke für die Erklrung :)

      Mein Edit 2 ist eine Ergänzung zum geposteten Code.
      Ich füge dort nur die Temperaturen 90° 80°, 70° und 60° zu meiner DataTable hinzu.
      Die 100° habe ich vergessen, bzw. dachte die brauche ich nicht.
      So. Ich habe jetzt noch eine kleine Einstellung hinzugefügt, in der ausgewählt werden kann, ob der Timer oben, oder unten und links, oder rechts angezeigt werden soll.
      Desweiteren habe ich noch den ein oder anderen Fehler ausgebügelt und den Code wieder hübsch geordnet.
      In diesem Projekt ist das wahrscheinlich nicht so wichtig, aber ich dachte mir, es kann nicht schaden, sich von Anfang an eine gescheite Strukurierung anzugewöhnen.

      Das nun fertige (ich würde glaube ich nichts mehr ändern - auch wenn die Formen selbst - designmäßig - sinnvoller gestaltet werden können) Projekt habe ich nochmal hochgeladen.

      Bitte schau(t) noch einmal drüber - jetzt sollte nix mehr zu meckern sein.
      Selbst der Name (Professional) macht so langsam Sinn :)

      Edit: Mist, jetzt gibt es doch noch einen Fehler.
      Auf dem PC, an dem ich das Projekt erstellt habe, habe ich die Helpers.dll, die Tea Timer.exe, sowie die Tee.xml aus dem Debug Ordner in ein neues Verzeichnis kopiert.
      Wenn ich nun in diesem PFad die .exe starte, geht alles wunderbar.
      Diesen Ordner habe ich dann in OneDrive hochgeladen und auf meinem Surface gestartet.
      Hier funktioniert jedoch das speichern der Settings nicht.
      Egal was ich in der Form Einstellungen ändere ist alles beim nächsten Programmstart weg.
      Habe ich irgendwie eine Datei vergessen?
      Dateien

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

      • Wenn man bei einer leeren Tee-Liste auf [löschen] klickt, kommt ne Exception -> Vorabprüfung auf leere Liste einbauen. Genauso bei den Gefäßen.
      • Man weiß instnktiv nicht, was mit [neu] und [löschen] gemeint ist
      • Das Menü ist mit |Datei| zwar standardbenannt, aber irreführend, da das Programm nichts mit Dateien macht - außer im Hintergrund. Entweder Du benennst es um (ggf. z.B. Aktionen?) oder Du lässt es ganz weg und der Benutzer beendet das Programm nur über [Ende], oder ggf. über das rote [X] rechts oben
      • kleiner Darstellungsfehler im Form Einstellungen beim G in "immer im Vordergrund"
      • ob man in den DGVs Zeilenhöhe und Zeilenkopfbreite frei wählbar lässt, ist Geschmacksfrage
      • Die Zeitgeber-Funktion im Gefäß-anlegen-Form ist ne gute Idee.
      • Man kann zwar viele Temperaturen (5er Schritte) beim Tee angeben, aber da die Gefäßtemperaturen nur in 10er-Schritten verfügbar ist, gibt es bei Tee mit 85 °C Solltemperatur Probleme
      • Du könntest ja alternativ auch ne Interpolation der Temperaturen einbauen. Wenn Du Die Zeiten von 100 °C -> 90 -> 80 -> 70 -> 60 hast, kannst Du ja ausrechnen lassen, wie lange das Wasser im ausgewählten Gefäß stehen muss, bis es ne bestimmte Temperatur erreicht hat. (vielleicht ist es linear, vielleicht nicht)
      • die default-Position ist mit "unten rechts" eingestellt. Dann taucht das Fenster aber oben links auf - aber auch nicht ganz; und: in der Liste gibt es als Auswahl den default-Eintrag gar nicht, sondern nur u.a. "rechts unten"
      • ggf. noch eine Plausibilitätsprüfung, da man im Nachhinein einstellen kann, dass das Wasser von 100 °C auf 100 °C 5 Minuten dauert, auf 90 °C aber nur 5 Sekunden
      • ob man die allgemeinen Einstellungen mit den Gefäßeinstellungen vermischt, ist ... eine Geschmacksfrage
      • Settings werden bei mir korrekt gespeichert
      • ab&zu kommt ne Exception, wenn man die Einstellungen aufruft. Habe aber noch kein Muster gefunden.
      • copy&paste-Fehler: In der Teeaendern-Sub ist die von mir gepostete Fehlermeldung noch mit falschen Sonderzeichen drin.
      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 1 mal editiert, zuletzt von „VaporiZed“ ()

      Huhu
      Wie immer vielen Dank :)

      Den Sachen werde ich mich später annehmen.
      Ich mache erstmal einen Updater.
      Es nervt mich tierisch, dass ich eine neue Version des Programms immer in die Cloud laden muss, um sie dann am nächsten Tag auf drei PCs (und es sollen demnächst vier werden, da ich meine Mudder als Betatester einspannen will - die Frau findet alle Fehler) herunter zu laden.
      Hierzu habe ich ein recht umfangreiches (ca. 1 Stunde) Youtube Tutorial gefunden.
      Ich finde das ganze ziemlich cool, und habe den Code immerhin schon zu ca. 90% verstanden.
      Also ich denke Ende der Woche gehts hier weiter.
      Oha, dann aber Vorsicht. Wenn Du Dich mit online-Updatern beschäftigst, sei Dir auch doch das hier ans Herz gelegt:
      nUpdate
      Hinweise für eigene Updater
      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.
      Man -.-
      Manchmal bist du ein echter Spielverderber. Aber vielen Dank für die Links.
      "Mein" Updater ist echt cool. Ist eine eigene Exe, die mit Kommandozeilenparametern gestartet wird und so alle nötigen Variablen erhält.
      Also ist er in jedem Projekt integrierbar.
      Dann wird die Updater.exe aus dem Hauptprogramm gestartet, die Updatesuche erkennt dann updates, zeigt changelog an.
      Das Hauptprogramm wird dann geschlossen, die exe ersetzt und das Programm wieder gestartet.

      Aber... die Sicherheit ... das kann ich ja quasi garnicht reinen Gewissens verwenden.
      Schon garnicht für die Zwecke auf die meine Programmierung hier hinausläuft.
      (Warenwirtschaftsystem, Bestelll- und Rechnungsverwaltung, usw.)

      Also verwerfe ich mein cooles Projekt wohl lieber wieder ganz schnell und setze mich mit NUpdate auseinander.
      Hallo ihr beiden
      @VaporiZed mein "Du bist ein Spielverderber" nehme ich zurück.
      nUpdate ist der Wahnsinn!

      Ich habe mir das ganze gestern angeschaut und die Funktionsweise verstanden.
      Ein kleines Testprogramm (ohne Funktion - nur zu Updatezwecken) habe ich erfolgreich mit nUpdate geupdatet.
      Mein eigenges Updateprogramm wahr natürlich ein Witz dagegen.
      Das einzige, was mich ein bisschen stört ist, dass wenn ich die "nUpdate.ProvideTAP.dll in ein Projekt integriere, der bin\Debug Ordner mit massig Dateien vollgehurt wird.
      Es werden insgesamt 5 dll, 5 xml und 2 pbd hinzugefügt.
      Da ist dann der Updater schnell mal größer als das Hauptprogramm.
      Aber ich nehme an (hab jetzt noch nicht getetstet), dass ich alles was keine dll ist in meinem fertigen Programm entfernen kann. Also hält es sich ja wieder in Grenzen.
      Und es ist ja auch eine irre Aufwertung für so ein Programm (von mir), also passt schon.

      Ich finds hammer! Dank für den Tipp - und danke für den "Sicherheitsbewusstsein" Hinweis.

      Frage hierzu:
      Bevor ich nun am Tea Timer weiterschreibe, werde ich natürlich auch hier nUpdate integrieren.
      Hier müsste ich wissen, ob ich das stört (denn ich könnte ja viele lustige Sachen bei einem Udate mit übertragen), dann lösch ichs raus, bevor ich hier das Programm hochlade.