Databinding an Chart mit mehreren Graphen

  • VB.NET

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

    Für eine neue Funktion von meinem Programm benötige ich wieder Hilfe und ich darf mich mit Datasets beschäftigen auch wenn ich sie immer noch verwirrend finde.
    Es sollen rund 60 Wertepaare per Hand eingegeben werden und es soll auch eine Überprüfung gegen Falscheingaben stattfinden.
    Die Wertepaare sollen dann in einem Array abgespeichert werden.
    - Wie kann ich das Datasset sortiert nach der ersten Spalte an ein Array übergeben?
    - Wie kann ich Falscheingaben abfangen?

    Bisher habe ich ein Dataset mit einem DGV verbunden. Mein bisheriges Programm habe ich auch angehängt.
    Bilder
    • oberfläche2.png

      38,36 kB, 641×478, 147 mal angesehen
    Dateien
    erstmal Benamung: Was wird da gemessen oder eingegeben - über was sind Frequenz und PhaseNoise Aussagen?

    egon schrieb:

    Die Wertepaare sollen dann in einem Array abgespeichert werden.
    Warum in einem Array? Warum nicht in einer Datei? Warum nicht in einer Xml-Datei?


    egon schrieb:

    - Wie kann ich das Datasset sortiert nach der ersten Spalte an ein Array übergeben?
    Weiß ich auch nicht - bist du dir sicher, dass genau ein Array dabei rauskommen soll?
    Weil zu deiner Chart-Vorgehensweise wären glaub 2 Arrays günstiger.

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

    Wenn ich eine Messkurve als Bild (s. Anlage) bekomme, möchte ich sie auch in meinem Programm in einem der Mem-Graphen einblenden können. Daher muss ich einige Messpunke aus dem Bild entnehmen und dann an das Programm übergeben, d.h. in eine Tabelle eintippen. Mit den Messwerten wird dann zweierlei gemacht:

    Die Kurve wird zum einen in einer Art Textfile gespeichert (s. Spoiler). Die Textdatei hat die Endung s1p. In der ersten Spalte steht die Frequenz und in der zweiten Spalte eine Größe die das Rauschen von einem Oszillator beschreibt (Phasenrauschen). Das ist eine Leistungsangabe in Watt (daher die kleinen Zahlen). In der Bilddatei ist diese Größe nur logarithmisch umgerechnet, damit man alles besser bildlich darstellen kann. D y-Wertebereich liegt zwischen 0,0 und -200,0 und der x-Wertebereich zwischen 1 und 1 000 000. Die Umrechnung ist ein kleiner Einzeiler und nicht das Problem.
    Es müssen also irgendwie die einzelne Wertepaare eingegeben und von Programm weiter verarbeitet werden können.
    Spoiler anzeigen
    ! Data written by
    # Hz S MA R 50
    5.8593750 0.0000456421 0.0000000000
    8.7890625 0.0000316595 0.0000000000
    11.7187500 0.0000167206 0.0000000000
    14.6484375 0.0000100849 0.0000000000
    17.5781250 0.0000065852 0.0000000000
    20.5078125 0.0000048173 0.0000000000
    23.4375000 0.0000039107 0.0000000000
    26.3671875 0.0000031675 0.0000000000
    29.2968750 0.0000024292 0.0000000000
    32.2265625 0.0000020426 0.0000000000
    35.1562500 0.0000018925 0.0000000000
    38.0859375 0.0000017392 0.0000000000
    41.0156250 0.0000015914 0.0000000000
    43.9453125 0.0000014260 0.0000000000
    46.8750000 0.0000012475 0.0000000000


    Dann soll die Kurve in meinem Programm dargestellt werden. Bei mir wird alles, wie dir bekannt, in Arrays der Form _CurveDatas(A_Mem1).XValues(i) und _CurveDatas(A_Mem1).YValues(i) abgelegt. Ja, du hast Recht, das sind zwei Array ;)

    Mein Problem ist nur, wie komm ich an die Daten, die ich über dasd DGV eingegeben habe, damit ich damit arbeiten kann.
    Bilder
    • Messkurve.png

      160,66 kB, 935×687, 103 mal angesehen
    Ich hab v.a. ein Benamungs-Problem.
    Und ich hab das Problem, dass bei deim Sample schonwieder der Microsoft.Visualbasic-Namespace general-importiert ist.
    Hab ich dir noch nie Visual Studio - Empfohlene Einstellungen ans Herz gelegt, dringlich?
    Mir war, als werde dort empfohlen, VS so einstellen, dass nagelneue Projekte von vorneherein diesen Deppen-Namespace nicht importieren.

    Deine Anwendung hat noch keinen sinnvollen Namen, und daher kannich dem Dataset auch keinen geben. Aber die Tabelle darin heißt offensichtlich Messpunkt oder so ähnlich.
    Puritaner würden jetzt noch empfehlen, sich zw. englisch und deutsch zu entscheiden, aber ich finde die Spalten Frequenz und PhaseNoise eiglich witzig - Denglisch rules!
    Jo, also die willst das nicht in ein oder 2 Arrays umwandeln sondern offenbar in ein CurveData - sag das doch! ;)
    Da passt zunächstmal der Datentyp nicht: Inne DataTable isses Decimal, im CurveData aber Double.
    Tatsächlich hast du aber glaub die Wahl zw. Double und Single, oder sogar Integer - weil (Hoch-)Frequenzen werden wohl kaum jemals Nachkommastellen aufweisen, oder?
    Und Integer braucht nur 1/4 Platz und ist v.a. zig-fach schneller inne Verarbeitung.

    VB.NET-Quellcode

    1. Private Function MesspunktTableCurveData(tb As MesspunktDataTable) As CurveData
    2. Dim rws = tb.Select(Function(rw) rw).ToArray
    3. Dim Frequencies = rws.Select(Function(rw) rw.Frequenz).ToArray
    4. Dim PhaseNoises = rws.Select(Function(rw) rw.PhaseNoise).ToArray
    5. Array.Sort(Frequencies, PhaseNoises) 'sortiert nach Frequencies
    6. Return New CurveData With {.Frequencies = Frequencies, .PhaseNoises = PhaseNoises}
    7. End Function
    8. '...
    9. Public Class CurveData
    10. Public Frequencies() As Integer
    11. Public PhaseNoises() As Integer
    12. Public LineColor As Color
    13. End Class
    Wie du siehst habe ich aufgrund der besseren Informations-Lage das CurveData auch gleich runderneuert.
    Ich kann dich beruhigen, dass ich in meinem Hauptprogramm schon die meisten Benennungen sinnhaftiger ausgeführt habe...
    In meinen Benennungen schwanke ich auch immer wieder zwischen der englischen und der deutschen Sprache. Wenn das Programm irgendwann mal fertig ist, wird alles auf der Programmoberfläche in englischer Sprach erfolgen. Bis dahin gibt es eine Übergangsfrist...

    Lauffähig kann aber mein kleines Beispielprogramm noch nicht bekommen. Ich habe es auch noch mal neu machen müssen, weil ich irgendwelche Fehlermeldungen gesehen habe, die ich nicht einordnen und beseitigen konnte.
    Ich habe nun ein Datatable mit dem Namen DataTable1 und ein DataSet mit dem Namen MesswerteDataSet und habe alles wie im Bild eingebunden.
    Der Datatable besteht aus
    ID (brauche ich noch nicht und vielleicht auch nie)
    frequency Int32 Hier ist es keine echte Einschränkung, wenn die Werte auf ganze Zahlen eingeschränkt werden. In meinem Hauptprogramm muss ich aber mit Single oder Double arbeiten - aber nicht bei einer Eingabe per Hand. Wenn mit über eine Datei-Einlese-Routine Daten geliefert werden, weisen sie Werte mit Kommastellen auf. Da alles Logarithmisch aufgetragen wird, können bei kleineren Werten auch Kommazahlen auftreten.
    phasenoise Single da es auch möglich sein soll, dass Werte wie -132,3 dBc einzugeben. Dieser Wert ist eine logarithmische Größe, die dann in Leistung pro Hz umgerechnet werden muss. Daher wird hier später mit Double gearbeitet.
    Ich habe mir gedacht, dass es später nicht geschickt ist, wenn in der Rechnung nicht Integer und Double vermischt werden (Fehlerquelle). Es ist vielleicht besser nur mit Double zu arbeiten.

    Um mein Beispiel irgendwie lauffähig zu machen brauche ich immer noch elementare Hilfe. Ich bin immer noch ein blutiger Anfänger :-(.
    Mein Beispiel habe ich in der aktuellen Form nochmals angehängt.
    Bilder
    • bild001.png

      16,84 kB, 691×334, 111 mal angesehen
    • bild002.png

      56,96 kB, 1.053×723, 107 mal angesehen
    Dateien
    Benenne deine DataTable so wie den Datentyp, den du erwartest - also im Form wird MesspunktDataTable erwartet, dann benenne deine DataTable zu Messpunkt

    Und die Imports-Anweisung hab ich unterschlagen:

    VB.NET-Quellcode

    1. Imports WindowsApplication1.MesswerteDataSet
    2. Public Class Form1
    3. Private Function MesspunktTable2CurveData(tb As MesspunktDataTable) As CurveData
    4. Dim rws = tb.Select(Function(rw) rw).ToArray
    5. Dim frequencies = rws.Select(Function(rw) rw.frequency).ToArray
    6. Dim phaseNoises = rws.Select(Function(rw) rw.Phasenoise).ToArray
    7. Array.Sort(frequencies, phaseNoises) '(paralell-)sortierung nach frequencies - phaseNoises-Elemente werden mit-geführt
    8. Return New CurveData With {.Frequencies = frequencies, .PhaseNoises = phaseNoises}
    9. End Function
    10. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    11. End Sub
    12. End Class
    13. Public Class CurveData
    14. Public Frequencies() As Integer
    15. Public PhaseNoises() As Single
    16. Public LineColor As Color
    17. End Class
    Und wirklich laufen tut da noch nix, das ist ja nur die Umwandlungs-funktion.
    Wie du die aufrufst, und was du dann mit dem CurveData machst, was sie dir zurückgibt, das ist in deim Sample ja nicht angelegt.

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

    Ich habe auch noch Probleme die Function MesspunktTable2CurveData richtig aufzurufen.
    Wie übergebe ich die Parameter richtig und was muss ich genau übergeben? Zeile 15 ist natürlich noch fehlerhaft.
    Fürs erste möchte ich einfach die Werte in den Arrays in _CurveDatas haben, so dass ich sie mir über Debug.WriteLine erst einmal ausgeben lassen kann.
    Dann kann ich hoffentlich alleine weiter machen...

    VB.NET-Quellcode

    1. Imports WindowsApplication1.MesswerteDataSet
    2. Public Class Form1
    3. Private _CurveDatas As CurveData() = {New CurveData()}
    4. Private Function MesspunktTable2CurveData(tb As MesspunktDataTable) As CurveData
    5. Dim rws = tb.Select(Function(rw) rw).ToArray
    6. Dim frequencies = rws.Select(Function(rw) rw.frequency).ToArray
    7. Dim phaseNoises = rws.Select(Function(rw) rw.Phasenoise).ToArray
    8. Array.Sort(frequencies, phaseNoises) '(paralell-)sortierung nach frequencies - phaseNoises-Elemente werden mit-geführt
    9. Return New CurveData With {.Frequencies = frequencies, .PhaseNoises = phaseNoises}
    10. End Function
    11. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    12. MesspunktTable2CurveData()
    13. End Sub
    14. End Class
    15. Public Class CurveData
    16. Public Frequencies() As Integer
    17. Public PhaseNoises() As Single
    18. Public LineColor As Color
    19. End Class

    och komm!
    guck die methode an, die erwartet einen Parameter, udn da steht auch welchen Datentyp der haben muss.
    Logisch kannste das nciht parameterlos aufrufen.
    Also gibt ihm eine MesspunktDataTable, und es gibt nur eine Möglichkeit, wo du diese MesspunktDataTable hernehmen kannst.

    (Mal abgesehen von New MesspunktDataTable - was ja Blödsinn wäre, denn eine neue MesspunktDataTable enthält mit Sicherheit keine Daten zum Konvertieren.)

    Also wo auf deinem verflixten Form findest du eine MesspunktDataTable, die bereits in Betrieb ist (Hint: etwa ein DGV könnte dran angebunden sein)?
    Grrrrr - ich bin immer noch blind (das grrrr bezieht sich auf mich...)

    Das DGV "DataGridView1" ist an die MesspunktBindingSource angebunden.
    Die "MesspunktBindingSource" hat als DataSource das "MesswerteDataSet" und als DataMember "Messpunkt".
    Der DataMember enthält "frequency" und "Phasenoise".

    Auch wenn ich das soweit nachvollziehen kann, bin ich aber trotzdem nicht in der Lage mir selbst zu helfen.
    Wie ich was übergeben muss habe ich trotzdem nicht herausbekommen :( Sorry

    VB.NET-Quellcode

    1. MesspunktTable2CurveData(Me.MesswerteDataSet.Messpunkt)
    Guck im ObjectBrowser nach und überzeuge dich, dass die MesswerteDataset-Klasse eine Property MessPunkt vom Datentyp MesspunktDataTable hat.
    Wenn also auf deim Form ein MesswerteDataset-Objekt herumfährt (guck im Designer - unten links, da isses!), dann hat das eine Property MessPunkt vom Datentyp MesspunktDataTable - so stehts im ObjectBrowser nachzulesen.
    Und dieser Messpunkt des MesswerteDatasets auf deim Form ist weitnbreit das einzige Objekt, was als Parameter für eine Konvertierung nach CurveData überhaupt in Frage kommt.
    Und du weißt ja bereits selbst, dass genau dieses Objekt mittels BindingSource auch ans DGV gebunden ist:

    egon schrieb:

    Das DGV "DataGridView1" ist an die MesspunktBindingSource angebunden.
    Die "MesspunktBindingSource" hat als DataSource das "MesswerteDataSet" und als DataMember "Messpunkt".
    Hast du das nu im OB überprüft?
    Oder willst du nochmal das Tut über den OB konsultieren?
    Hab ich einen ZusatzPost drangemacht, weil scheinbar ist der bei vielen schlecht eingerichtet, und dann nicht so übersichtlich wie er sollte:
    VisualStudio richtig nutzen (Google ist nicht deine Mami)


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

    So, nun läuft es erst einmal und ich habe es geschafft eine leere und eine falsche Eingabe (z.B. Buchstaben) abzufangen. Ob diese Fehlerbehandlung geschickter aufgebaut werden kann, kann ich nicht beurteilen.
    Kann man das auch so einstellen, dass für frequency und Phasenoise nur bestimmte Intervalle bei der Eingabe zulässig sind?
    frequency: 1 bis 1 000 000
    Phasenoise: -30,0 bis -200
    Später werde ich auch Zeilen, in denen ein Element den Wert Null hat einfach löschen.
    Später müssen auch Zeilen mit gleicher Frequenzangabe erkannt und angezeigt werden. Dass muss heraus gefiltert und vom Nutzer korrigiert werden.

    Nun habe ich es auch im Objektbrowser überprüft. Da hätte ich drauf kommen sollen...
    Deine Zusatzpost werde ich noch lesen.
    Nochmals vielen Dank für die Hilfe

    Hier mein aktueller Code:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private _CurveDatas As CurveData() = {New CurveData()}
    3. Private Function MesspunktTable2CurveData(tb As MesspunktDataTable) As CurveData
    4. Dim rws = tb.Select(Function(rw) rw).ToArray
    5. Dim frequencies = rws.Select(Function(rw) rw.frequency).ToArray
    6. Dim phaseNoises = rws.Select(Function(rw) rw.Phasenoise).ToArray
    7. Array.Sort(frequencies, phaseNoises) '(paralell-)sortierung nach frequencies - phaseNoises-Elemente werden mit-geführt
    8. Return New CurveData With {.Frequencies = frequencies, .PhaseNoises = phaseNoises}
    9. End Function
    10. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    11. _CurveDatas(0) = MesspunktTable2CurveData(Me.MesswerteDataSet.Messpunkt)
    12. For i = 0 To _CurveDatas(0).Frequencies.Length - 1
    13. Debug.WriteLine(_CurveDatas(0).Frequencies(i).ToString & " " & _CurveDatas(0).PhaseNoises(i).ToString)
    14. Next
    15. End Sub
    16. Private Sub DataGridView1_DataError(ByVal sender As Object, ByVal e As DataGridViewDataErrorEventArgs) Handles DataGridView1.DataError
    17. MessageBox.Show("Es muss eine Zahl eingegeben werden." & Environment.NewLine & "Vorher kann dieses Fenster nicht mehr verlassen werden")
    18. End Sub
    19. End Class
    20. Public Class CurveData
    21. Public Frequencies() As Integer
    22. Public PhaseNoises() As Single
    23. Public LineColor As Color
    24. End Class

    Bilder
    • DBNull ersetzen.png

      20,19 kB, 598×392, 107 mal angesehen

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

    Ich denke mal, das wird ein Eingabe-Dialog, also etwas, was du öffnest, der User gibt sein Kram ein, und nachm Schließen werden die Eingaben verarbeitet.
    Dialoge: Instanziierung von Forms und Aufruf von Dialogen kennste?
    Und da kannst du dann das Form_Closing oder Form_Validating - Event behandeln, und die Eingaben validieren, und ggfs. e.Cancel=True setzen, sodass der User seine Eingaben korrigieren muss.
    Ich bin momentan beim beim Überarbeiten von meinem Programm und habe die Frage, wie man testen kann, ob ein Array gefüllt ist?
    Also konkret: Wie kann man am besten testen ob _CurveDatas(A_Mem2).XValues() überhaupt existiert. Es kann mal sein, dass in einer Anzeige-Routine ein Array noch leer ist und bestimmte Elemente nicht angezeigt werden können. Diese Fall möchte ich abfangen, damit mein Programm an diesen Stellen nicht abstürzt. Ist der richtige Weg mit Try-Catch-EndTry oder sollte man dies anders lösen?
    ein Array ist nicht gefüllt, wenn es leer ist. Dann ist seine Length-Property 0.
    Sowas verursacht aber keine Abstürze.

    Die Frage ist, ob eine Array (oder sonstige) Variable zugewiesen ist. Um das zu testen verwendet man den Is - Operator

    VB.NET-Quellcode

    1. If myItem is Nothing then Messagebox.Show("falls myItem ein Array ist, so kann nichtmal Length abgerufen werden, denn Nothing hat kein Length. Es ist einfach nicht da.")


    Kein TryCatch. Programmier sauber, und sorge halt dafür, dass die Variablen zugewiesen sind, bevor du sie verwendest. Dann brauchst du in 95% der Fälle nichtmal auf Nothing zu testen.

    Insbesondere die NullReferenceException ist nicht dein Feind, sondern dein bester Verbündeter beim sauberen Programmieren. Gugge vlt. Exceptions, und was sie uns sagen wollen

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