2010-09-17 13 views
14

Ich verwende derzeit die Erstellung von Diagrammen in .NET mit System.Windows.Forms.DataVisualization.Charting.Chart. Bis jetzt scheint es sehr mächtig und funktioniert großartig. Es gibt jedoch ein großes Problem hinsichtlich der automatischen Berechnung von Intervallen. Ich benutze viele double Werte, und in Bibliotheken wie ZedGraph, behandelt es das perfekt. Es wählt Min/Max/Intervall ganz gut. In MS Chart kann jedoch mindestens 206.3334539832 und Intervalle mit einer ähnlichen Dezimalgenauigkeit ausgewählt werden. Offensichtlich sieht das ziemlich hässlich aus.Auto-Intervall-Genauigkeit in MS-Diagramm

Also habe ich versucht, einfach das Achsenformat {0.00} und es funktioniert gut, wenn es das Diagramm lädt. Außer wenn Sie heranzoomen, benötigen Sie eine größere Genauigkeit, vielleicht 4 Dezimalstellen anstelle von 2. Es scheint, dass ich entweder ständig mit 9 Dezimalstellen festhaue oder eine konstante feste Zahl, die brechen kann, wenn jemand eine höhere Genauigkeit benötigt. Ich möchte lieber die Präzision basierend auf der Ebene des Zooms, die derzeit angewendet wird, aufgreifen. Bibliotheken wie ZedGraph und Dundas (die meiner Meinung nach MS sogar benutzt!) Neigen dazu, gute Werte zu wählen, die sich beim Hinein- und Herauszoomen ändern.

Gibt es eine Möglichkeit, die Intervalle zu ändern, wenn sich der Zoomrahmen ändert? Es ist wahrscheinlich eine einfache Eigenschaft, die ich falsch gesetzt habe, aber es ist schwer zu sagen mit den Millionen von Eigenschaften, die dieses Ding hat (besonders wenn es ungefähr 14 Orte gibt, die das Konzept von Interval darstellen).

+2

AFAIK werden die Charting Kontrollen basierend auf Dundas Kontrollen. Microsoft hat vor einiger Zeit die Datenvisualisierungskomponenten von Dundas erworben. Weitere Informationen [hier] (http://blogs.msdn.com/b/bimusings/archive/2007/06/04/microsoft-acquires-dundas-s-data-visualization-components-sql-2008-news-download- ctp3.aspx) – CGK

+0

Es sind keine Bilder in deinem Schnitt? – noelicus

+0

@noelicus Es tut uns leid, neuer Job seither und diese Bilder wurden irgendwann runtergenommen (anscheinend war das vor dem SO, was das Hochladen von Bildern zuließ). Ich habe die Bearbeitung für jetzt entfernt. Ich werde nachsehen und sehen, ob ich eine Kopie dieser Bilder finden kann, und diese Frage aktualisieren, wenn ich kann. – drharris

Antwort

5

Ich hatte genau das gleiche Problem beim Zoomen. Ich habe Code hinzugefügt, um die Achsenbeschriftungen zu formatieren und sie vom Paint-Handler aus aufzurufen. Die Axis View-Objekte haben eine IsZoomed-Eigenschaft und Funktionen zum Abrufen der aktuellen Achsenlimits (GetViewMinimum/Maximum). Ich setze das Axis LabelStyle.Format für alle Fälle auf "N", es sei denn, der Max-Min = Bereich ist kleiner als 1. Dann setze ich das Format auf "F #", wobei # basierend auf dem Achsenbereich berechnet wird.

# = Convert.ToInt32(Math.Abs(Math.Log10(range) - .5)) + 1; 
+0

Vielen Dank für GetViewMinimum/Maximum! Dies sind wahrscheinlich die Funktionen, nach denen ich gesucht habe. Ich werde das bald versuchen, und wenn es für meinen Fall funktioniert, werde ich meine vorherige Belohnung wieder einsetzen und es Ihnen geben. Danke auch für den Code, um Nachkommastellen zu bekommen - nach einigen Tests in WolframAlpha scheint es die perfekte Anzahl von Dezimalzahlen zu erzeugen. – drharris

+0

Ich habe vergessen zu berichten, aber ich hatte endlich Zeit zu verbringen, um dies zu implementieren, und es funktioniert PERFEKT. Ich denke immer noch, dass das Steuerelement selbst mit dieser Art von Logik umgehen sollte (wenn Open-Source-Projekte wie ZedGraph das können, sicherlich MS/Dundas). Ich habe die ursprüngliche Prämie für diese Frage wieder eingeführt, da dies mir viele Kopfschmerzen von unglücklichen Kunden erspart! Ich werde es vergeben, sobald SO es mir erlaubt. – drharris

1

Nachdem ich mit der Diagrammsteuerung herumgespielt habe, war ich nicht in der Lage, eine einfache Lösung für Ihr Problem zu finden. Folgendes kann jedoch helfen:

Haben Sie in Betracht gezogen, die Maximal- und Minimalwerte für die Achsen selbst festzulegen? Wenn Sie die tatsächlichen Maximal- und Minimalwerte auf die nächste sinnvolle "Runden" -Nummer (5, 10, 0,5, 0,01) runden, sollte dies die berechneten Intervalle ein wenig freundlicher machen.

Ich verstehe, dies ist keine ideale Lösung, aber durch sorgfältige Auswahl der maximalen und/oder minimalen Werte können Sie sicherstellen, dass die Intervalle "netter" Zahlen sind. Wenn der Bereich Ihrer Achsen durch 2 teilbar ist, sollte es in ziemlich schönen Intervallen resultieren.

+0

Ich habe versucht, Min und Max selbst einzustellen, aber diese Diagramme werden für die Analyse verwendet, und sobald Sie in eine benutzerdefinierte Region hineinzoomen, verliert sie die schönen runden Zahlen und kehrt zu diesem unerwünschten Verhalten zurück. Darüber hinaus führt das Festlegen des Minimums auf -10 manchmal zu -10,00000023 oder ähnlichem. Du bist also auf halbem Weg; Es wird zwar die anfängliche Anzeige korrigiert, aber mit all dem Zoomen, das passieren wird, ist es keine vollständige Lösung für das Problem. Gut zu hören, dass ich nicht der Einzige bin! – drharris

0

Um das Ergebnis mit minimal Kosten bieten Sie exponentielles wissenschaftliches Format

+0

Wenn dies eine firmeninterne Anwendung wäre, die nur von wissenschaftsorientierten Menschen verwendet wird, wäre das großartig! Wir haben jedoch eine Nutzerbasis, die vom Universitätsprofessor bis zum Farmer reicht. Einige dieser Leute zu lehren, exponentielle Formate zu lesen, wäre fast unmöglich. Auch die Verwendung von wissenschaftlichen Zahlen verhindert nicht das Problem von zu vielen Dezimalstellen (wie in 2.6666684583e-4) – drharris

+0

Verwenden Sie einfach string.Format ("{0: e2}", 123.456789). Versuchen Sie auch, benutzerdefinierte Konverter Formatierer anzuwenden. – gabba

1

Warum ändert nicht die Nummer Format-String verwenden können.

erstellen Format-String

string formatString = "{0.00"; 

identifizieren Zoomstufe, sagen zoomlevel = 2;

formatString = formatString.PadRight(5+zoomLevel, '0'); 
formatString += "}"; 

Verwenden Sie jetzt dieses Format für die Achsenlegende. Verwenden Sie den String-Builder oder eine bessere Möglichkeit, die Formatzeichenfolge zu ändern.

+0

Das Problem ist, dass "Zoom Level" wenig Bedeutung hat. Die Skala wird nicht immer die gleiche sein (manchmal kann die X-Achse im Bereich von 100-120 liegen und manchmal von 0-4000). Außerdem kann der Benutzer selbst ein Zoom-Fenster auswählen, was bedeutet, dass es keine explizite Möglichkeit gibt, zu bestimmen, auf wie viele Dezimalstellen zu formatieren ist. Gute Antwort in der Theorie, aber es passt einfach nicht zum Objektmodell hier. – drharris

0

Sie können an anpassen anpassen Ereignis. Von dort können Sie die Etiketten auf der x-Achse ändern:

var xAxisLabels = chart1.ChartAreas[0].AxisX.CustomLabels; 
... 
xAxisLabels[0].Text = ... 

Set min. und max. Werte:

chart1.ChartAreas[0].AxisX.Maximum = ...; 

usw.

0

Sie die Maximal- und Minimal basierend auf Ihren Datensatz dynamisch aktualisieren können.Jedes Mal, wenn der Benutzer zoomt, machst du einen FOREACH an jedem Punkt und erhalte die Statistiken und basierend auf diesem Set deine max und min

+0

Code? Wie erkennt man, wenn der Benutzer zoomt? Wie kann man nur Punkte im Fenster finden, während der Zoom aktiv ist? – drharris

0

Es hilft, den IntervalOffset der Achse zu setzen, hier ein Beispiel:

Private Sub chMap_AxisViewChanged(sender As System.Object, e As System.Windows.Forms.DataVisualization.Charting.ViewEventArgs) Handles chMap.AxisViewChanged 
    'the grid ticks are rounded values 
    e.Axis.IntervalOffset = -e.Axis.ScaleView.ViewMinimum 
End Sub