Files
elwig/Elwig/Windows/ChartWindow.xaml.cs

750 lines
27 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Elwig.Helpers;
using Elwig.Helpers.Billing;
using Elwig.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using ScottPlot;
using ScottPlot.Plottable;
namespace Elwig.Windows {
public partial class ChartWindow : AdministrationWindow {
private readonly int Year = 2021;
private readonly int AvNr = 2;
private ScatterPlot OechslePricePlotScatter;
private MarkerPlot HighlightedPoint;
private MarkerPlot PrimaryMarkedPoint;
private MarkerPlot SecondaryMarkedPoint;
private Tooltip Tooltip;
private int LastHighlightedIndex = -1;
private int HighlightedIndex = -1;
private int PrimaryMarkedPointIndex = -1;
private int SecondaryMarkedPointIndex = -1;
private bool HoverChanged = false;
private bool HoverActive = false;
private const int MinOechsle = 50;
private const int MaxOechsle = 140;
private Graph? Graph;
public ChartWindow() {
InitializeComponent();
ExemptInputs = new Control[] {
GraphList, OechsleInput, PriceInput, FreeZoomInput, GradationLinesInput, TooltipInput
};
}
private void Window_Loaded(object sender, RoutedEventArgs evt) {
LockInputs();
OechslePricePlot.IsEnabled = false;
}
private async Task RefreshGraphList() {
await Context.PaymentVariants.LoadAsync();
await RefreshGraphListQuery();
}
private async Task RefreshGraphListQuery(bool updateSort = false) {
List<PaymentVar> paymentVars = await Context.PaymentVariants.Where(p => p.Year == Year && p.AvNr == AvNr).ToListAsync();
if (paymentVars.Count != 1) {
return;
}
PaymentVar paymentVar = paymentVars[0];
var data = JsonNode.Parse(paymentVar.Data).AsObject();
var auszahlungsSorten = data["AuszahlungSorten"]?.AsObject();
if (auszahlungsSorten == null) {
return;
}
var Graphs = auszahlungsSorten["Kurven"]?.AsArray();
if (Graphs == null) {
return;
}
List<Graph> GraphsList = new();
int i = 1;
foreach (var graph in Graphs) {
GraphsList.Add(new Graph("Oe", i, graph?.AsObject(), ParseContracts(auszahlungsSorten, i - 1), 50, 140));
i++;
}
ControlUtils.RenewItemsSource(GraphList, GraphsList, g => (g as Graph)?.Num);
if (GraphsList.Count == 1) {
GraphList.SelectedIndex = 0;
}
RefreshInputs();
}
private String ParseContracts(JsonObject auszahlungsSorten, int num) {
List<string> contracts = new();
foreach (var sorte in auszahlungsSorten) {
if (sorte.Key == "Kurven") continue;
foreach (var attribut in sorte.Value.AsObject()) {
foreach (var bindung in attribut.Value.AsObject()) {
if ((int)bindung.Value.AsValue() == num) {
contracts.Add($"{sorte.Key}/{attribut.Key}/{bindung.Key}");
}
}
}
}
return string.Join("\n", contracts.ToArray());
}
private async Task<bool> RemoveGraph(int num) {
List<PaymentVar> paymentVars = await Context.PaymentVariants.Where(p => p.Year == Year && p.AvNr == AvNr).ToListAsync();
if (paymentVars.Count != 1) {
return false;
}
PaymentVar paymentVar = paymentVars[0];
var data = JsonNode.Parse(paymentVar.Data).AsObject();
var auszahlungsSorten = data["AuszahlungSorten"]?.AsObject();
if (auszahlungsSorten == null) {
return false;
}
var Graphs = auszahlungsSorten["Kurven"]?.AsObject();
if (Graphs == null) {
return false;
}
int i = 1;
foreach (var graph in Graphs) {
if (i == num) {
Graphs.Remove(graph.Key);
break;
}
i++;
}
foreach (var sorte in auszahlungsSorten) {
if (sorte.Key == "Kurven") continue;
foreach (var attribut in sorte.Value.AsObject()) {
var bindungen = attribut.Value.AsObject();
foreach (var bindung in bindungen) {
int v = (int)bindung.Value;
if (v == num - 1) {
bindungen.Remove(bindung.Key);
} else if (v > num - 1) {
bindungen[bindung.Key] = v - 1;
}
}
}
}
EntityEntry<PaymentVar>? tr = null;
try {
paymentVar.Data = data.ToString();
tr = Context.Update(paymentVar);
await Context.SaveChangesAsync();
} catch (Exception exc) {
if (tr != null) await tr.ReloadAsync();
var str = "Der Eintrag konnte nicht in der Datenbank gelöscht werden!\n\n" + exc.Message;
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
MessageBox.Show(str, "Graph löschen", MessageBoxButton.OK, MessageBoxImage.Error);
}
return true;
}
private void RefreshInputs(bool validate = false) {
ResetPlot();
ClearInputStates();
if (GraphList.SelectedItem is Graph g) {
EditButton.IsEnabled = true;
DeleteButton.IsEnabled = true;
EnableOptionButtons();
FillInputs(g);
} else {
EditButton.IsEnabled = false;
DeleteButton.IsEnabled = false;
DisableOptionButtons();
ClearOriginalValues();
ClearInputs(validate);
ClearInputStates();
}
GC.Collect();
}
private void FillInputs(Graph g) {
ClearOriginalValues();
Graph = (Graph)g.Clone();
GraphNumberInput.Text = Graph.Num.ToString();
if (Graph.Type == "oe") {
OechsleGraphType_Input.IsChecked = true;
} else if (Graph.Type == "kmw") {
KmwGraphType_Input.IsChecked = true;
}
InitPlot();
OechslePricePlot.IsEnabled = true;
FinishInputFilling();
}
private void InitInputs() {
GraphNumberInput.Text = (GraphList.Items.Count + 1).ToString();
OechsleGraphType_Input.IsChecked = true;
FinishInputFilling();
}
protected override async Task OnRenewContext() {
await base.OnRenewContext();
await RefreshGraphList();
}
private void InitPlot() {
OechslePricePlotScatter = OechslePricePlot.Plot.AddScatter(Graph.DataX, Graph.DataY);
OechslePricePlot.Configuration.DoubleClickBenchmark = false;
OechslePricePlotScatter.LineColor = Color.Blue;
OechslePricePlotScatter.MarkerColor = Color.Blue;
OechslePricePlotScatter.MarkerSize = 9;
//OechslePricePlot.Plot.XAxis.ManualTickSpacing(1);
OechslePricePlot.Plot.YAxis.ManualTickSpacing(0.1);
OechslePricePlot.Plot.SetAxisLimits(MinOechsle - 1, MaxOechsle + 1, -0.1, 2);
OechslePricePlot.Plot.Layout(padding: 0);
OechslePricePlot.Plot.XAxis2.Layout(padding: 0);
OechslePricePlot.Plot.YAxis.Layout(padding: 0);
OechslePricePlot.Plot.YAxis2.Layout(padding: 0);
HighlightedPoint = OechslePricePlot.Plot.AddPoint(0, 0);
HighlightedPoint.Color = Color.Red;
HighlightedPoint.MarkerSize = 10;
HighlightedPoint.MarkerShape = MarkerShape.openCircle;
HighlightedPoint.IsVisible = false;
PrimaryMarkedPoint = OechslePricePlot.Plot.AddPoint(0, 0);
PrimaryMarkedPoint.Color = Color.Red;
PrimaryMarkedPoint.MarkerSize = 6;
PrimaryMarkedPoint.MarkerShape = MarkerShape.filledCircle;
PrimaryMarkedPoint.IsVisible = false;
SecondaryMarkedPoint = OechslePricePlot.Plot.AddPoint(0, 0);
SecondaryMarkedPoint.Color = Color.Red;
SecondaryMarkedPoint.MarkerSize = 6;
SecondaryMarkedPoint.MarkerShape = MarkerShape.filledCircle;
SecondaryMarkedPoint.IsVisible = false;
OechslePricePlot.Refresh();
RefreshFreeZoom();
RefreshGradationLines();
}
private void ResetPlot() {
Graph = null;
PrimaryMarkedPointIndex = -1;
OechslePricePlot.Plot.Remove(OechslePricePlotScatter);
OechslePricePlot.Plot.Clear();
OechslePricePlot.Reset();
OechslePricePlot.Refresh();
}
private void ChangeMarker(MarkerPlot point, bool visible, double x = 0, double y = 0) {
point.X = x;
point.Y = y;
point.IsVisible = visible;
}
private void FlattenGraph(int begin, int end, double value) {
for (int i = begin; i <= end; i++) {
Graph.DataY[i] = value;
}
OechslePricePlot.Render();
}
private void LinearIncreaseGraph(int begin, int end, double inc) {
for (int i = begin; i < end; i++) {
Graph.DataY[i + 1] = Graph.DataY[i] + inc;
}
OechslePricePlot.Render();
}
private void EnableActionButtons() {
LeftFlatButton.IsEnabled = true;
RightFlatButton.IsEnabled = true;
LinearIncreaseButton.IsEnabled = true;
}
private void DisableActionButtons() {
LeftFlatButton.IsEnabled = false;
RightFlatButton.IsEnabled = false;
InterpolateButton.IsEnabled = false;
LinearIncreaseButton.IsEnabled = false;
}
private void FreeZoomInput_Changed(object sender, RoutedEventArgs evt) {
RefreshFreeZoom();
}
private void RefreshFreeZoom() {
if (FreeZoomInput.IsChecked == true) {
UnlockZoom();
} else {
LockZoom();
}
OechslePricePlot.Refresh();
}
private void LockZoom() {
OechslePricePlot.Plot.XAxis.SetBoundary(MinOechsle - 1, MaxOechsle + 1);
OechslePricePlot.Plot.YAxis.SetBoundary(-0.1, 2);
OechslePricePlot.Plot.XAxis.SetZoomOutLimit(MaxOechsle - MinOechsle + 2);
OechslePricePlot.Plot.YAxis.SetZoomOutLimit(2.1);
OechslePricePlot.Plot.SetAxisLimits(MinOechsle - 1, MaxOechsle + 1, -0.1, 2);
}
private void UnlockZoom() {
OechslePricePlot.Plot.XAxis.SetBoundary();
OechslePricePlot.Plot.YAxis.SetBoundary();
OechslePricePlot.Plot.XAxis.SetZoomOutLimit((MaxOechsle - MinOechsle) * 1.5);
OechslePricePlot.Plot.YAxis.SetZoomOutLimit(3.5);
}
private void EnableOptionButtons() {
FreeZoomInput.IsEnabled = true;
GradationLinesInput.IsEnabled = true;
TooltipInput.IsEnabled = true;
}
private void DisableOptionButtons() {
FreeZoomInput.IsEnabled = false;
GradationLinesInput.IsEnabled = false;
TooltipInput.IsEnabled = false;
}
private void GradationLinesInput_Changed(object sender, RoutedEventArgs evt) {
RefreshGradationLines();
}
private void RefreshGradationLines() {
if (GradationLinesInput.IsChecked == true) {
ShowGradationLines();
ShowLegend();
} else {
HideGradationLines();
HideLegend();
}
OechslePricePlot.Refresh();
}
private void ShowGradationLines() {
OechslePricePlot.Plot.AddVerticalLine(68, Color.Red, 2, label: "68 Oechsle (LDW)");
OechslePricePlot.Plot.AddVerticalLine(73, Color.Orange, 2, label: "73 Oechsle (QUW)");
OechslePricePlot.Plot.AddVerticalLine(84, Color.Green, 2, label: "84 Oechsle (KAB)");
}
private void HideGradationLines() {
OechslePricePlot.Plot.Clear(typeof(VLine));
}
private void ShowLegend() {
OechslePricePlot.Plot.Legend(true, Alignment.UpperRight);
}
private void HideLegend() {
OechslePricePlot.Plot.Legend(false, Alignment.UpperRight);
}
private void OechsleInput_TextChanged(object sender, RoutedEventArgs evt) {
IntegerInput_TextChanged(sender, evt);
bool success = int.TryParse(OechsleInput.Text, out int oechsle);
SecondaryMarkedPointIndex = -1;
ChangeMarker(SecondaryMarkedPoint, false);
if (success) {
if (oechsle >= MinOechsle && oechsle <= MaxOechsle) {
PrimaryMarkedPointIndex = oechsle - MinOechsle;
ChangeMarker(PrimaryMarkedPoint, true, Graph.DataX[PrimaryMarkedPointIndex], Graph.DataY[PrimaryMarkedPointIndex]);
PriceInput.Text = Graph.DataY[PrimaryMarkedPointIndex].ToString();
if (IsEditing || IsCreating) EnableActionButtons();
OechslePricePlot.Render();
return;
}
}
PrimaryMarkedPointIndex = -1;
ChangeMarker(PrimaryMarkedPoint, false);
DisableActionButtons();
PriceInput.Text = "";
OechslePricePlot.Render();
}
private void PriceInput_TextChanged(object sender, RoutedEventArgs evt) {
if (PrimaryMarkedPointIndex != -1) {
bool success = Double.TryParse(PriceInput.Text, out double price);
if (success) {
Graph.DataY[PrimaryMarkedPointIndex] = price;
PrimaryMarkedPoint.Y = price;
SaveButton.IsEnabled = true;
ResetButton.IsEnabled = true;
OechslePricePlot.Refresh();
}
}
}
private void LeftFlatButton_Click(object sender, RoutedEventArgs evt) {
if (PrimaryMarkedPointIndex == -1) {
return;
}
FlattenGraph(0, PrimaryMarkedPointIndex, Graph.DataY[PrimaryMarkedPointIndex]);
SaveButton.IsEnabled = true;
ResetButton.IsEnabled = true;
}
private void RightFlatButton_Click(object sender, RoutedEventArgs evt) {
if (PrimaryMarkedPointIndex == -1) {
return;
}
FlattenGraph(PrimaryMarkedPointIndex, Graph.DataY.Length - 1, Graph.DataY[PrimaryMarkedPointIndex]);
SaveButton.IsEnabled = true;
ResetButton.IsEnabled = true;
}
private void InterpolateButton_Click(object sender, RoutedEventArgs evt) {
int steps = Math.Abs(PrimaryMarkedPointIndex - SecondaryMarkedPointIndex);
if (PrimaryMarkedPointIndex == -1 || SecondaryMarkedPointIndex == -1 || steps < 2) {
return;
}
var (lowIndex, highIndex) = PrimaryMarkedPointIndex < SecondaryMarkedPointIndex ? (PrimaryMarkedPointIndex, SecondaryMarkedPointIndex): (SecondaryMarkedPointIndex, PrimaryMarkedPointIndex);
double step = (Graph.DataY[highIndex] - Graph.DataY[lowIndex]) / steps;
for (int i = lowIndex; i < highIndex - 1; i++) {
Graph.DataY[i + 1] = Math.Round(Graph.DataY[i] + step, 4); // TODO richtig runden
}
SaveButton.IsEnabled = true;
ResetButton.IsEnabled = true;
}
private void LinearIncreaseButton_Click(object sender, RoutedEventArgs e) {
if (PrimaryMarkedPointIndex == -1) {
return;
}
double? priceIncrease = Utils.ShowLinearPriceIncreaseDialog();
if (priceIncrease == null) {
return;
}
LinearIncreaseGraph(PrimaryMarkedPointIndex, Graph.DataY.Length - 1, priceIncrease.Value);
SaveButton.IsEnabled = true;
ResetButton.IsEnabled = true;
}
private void OechslePricePlot_MouseDown(object sender, MouseEventArgs e) {
if (!IsCreating && GraphList.SelectedItem == null) {
return;
}
if (HoverActive) {
if ((IsEditing || IsCreating) && Keyboard.IsKeyDown(Key.LeftCtrl)) {
if (PrimaryMarkedPointIndex == -1) {
return;
}
SecondaryMarkedPointIndex = HighlightedIndex;
ChangeMarker(SecondaryMarkedPoint, true, Graph.DataX[SecondaryMarkedPointIndex], Graph.DataY[SecondaryMarkedPointIndex]);
InterpolateButton.IsEnabled = true;
return;
}
PrimaryMarkedPointIndex = HighlightedIndex;
ChangeMarker(PrimaryMarkedPoint, true, Graph.DataX[PrimaryMarkedPointIndex], Graph.DataY[PrimaryMarkedPointIndex]);
OechsleInput.Text = Graph.DataX[HighlightedIndex].ToString();
PriceInput.Text = Graph.DataY[HighlightedIndex].ToString();
if (IsEditing || IsCreating) {
EnableActionButtons();
}
} else {
PrimaryMarkedPointIndex = -1;
SecondaryMarkedPointIndex = -1;
ChangeMarker(PrimaryMarkedPoint, false);
ChangeMarker(SecondaryMarkedPoint, false);
OechsleInput.Text = "";
PriceInput.Text = "";
DisableActionButtons();
}
}
private void OechslePricePlot_MouseMove(object sender, MouseEventArgs e) {
if (!IsCreating && GraphList.SelectedItem == null) {
return;
}
(double mouseCoordX, double mouseCoordY) = OechslePricePlot.GetMouseCoordinates();
double xyRatio = OechslePricePlot.Plot.XAxis.Dims.PxPerUnit / OechslePricePlot.Plot.YAxis.Dims.PxPerUnit;
(double pointX, double pointY, int pointIndex) = OechslePricePlotScatter.GetPointNearest(mouseCoordX, mouseCoordY, xyRatio);
(double mousePixelX, double mousePixelY) = OechslePricePlot.GetMousePixel();
(double pointPixelX, double pointPixelY) = OechslePricePlot.Plot.GetPixel(pointX, pointY);
HighlightedIndex = LastHighlightedIndex;
if (Math.Abs(mousePixelX - pointPixelX) < 3 && Math.Abs(mousePixelY - pointPixelY) < 3) {
ChangeMarker(HighlightedPoint, true, pointX, pointY);
HighlightedPoint.IsVisible = true;
HoverChanged = true ^ HoverActive;
HoverActive = true;
} else {
ChangeMarker(HighlightedPoint, false);
HoverChanged= false ^ HoverActive;
HoverActive= false;
OechslePricePlot.Plot.Remove(Tooltip);
OechslePricePlot.Render();
}
if (LastHighlightedIndex != HighlightedIndex || HoverChanged) {
OechslePricePlot.Plot.Remove(Tooltip);
if (TooltipInput.IsChecked == true) {
Tooltip = OechslePricePlot.Plot.AddTooltip($"Oechsle: {pointX:N2}, Preis: {Math.Round(pointY, 4)})", pointX, pointY);
}
LastHighlightedIndex = pointIndex;
HoverChanged = false;
OechslePricePlot.Render();
}
}
override protected void UpdateButtons() {
if (!IsEditing && !IsCreating) return;
bool ch = HasChanged, v = IsValid;
}
private void DisableNewEditDeleteButtons() {
NewButton.IsEnabled = false;
EditButton.IsEnabled = false;
DeleteButton.IsEnabled = false;
}
private void EnableNewEditDeleteButtons() {
NewButton.IsEnabled = true;
EditButton.IsEnabled = GraphList.SelectedItem != null;
DeleteButton.IsEnabled = GraphList.SelectedItem != null;
}
private void ShowSaveResetCancelButtons() {
SaveButton.IsEnabled = false;
ResetButton.IsEnabled = false;
CancelButton.IsEnabled = true;
SaveButton.Visibility = Visibility.Visible;
ResetButton.Visibility = Visibility.Visible;
CancelButton.Visibility = Visibility.Visible;
}
private void HideSaveResetCancelButtons() {
SaveButton.IsEnabled = false;
ResetButton.IsEnabled = false;
CancelButton.IsEnabled = false;
SaveButton.Visibility = Visibility.Hidden;
ResetButton.Visibility = Visibility.Hidden;
CancelButton.Visibility = Visibility.Hidden;
}
private void ShowNewEditDeleteButtons() {
EnableNewEditDeleteButtons();
NewButton.Visibility = Visibility.Visible;
EditButton.Visibility = Visibility.Visible;
DeleteButton.Visibility = Visibility.Visible;
}
private void HideNewEditDeleteButtons() {
DisableNewEditDeleteButtons();
NewButton.Visibility = Visibility.Hidden;
EditButton.Visibility = Visibility.Hidden;
DeleteButton.Visibility = Visibility.Hidden;
}
private void NewButton_Click(object sender, RoutedEventArgs e) {
IsCreating = true;
GraphList.IsEnabled = false;
GraphList.SelectedItem = null;
HideNewEditDeleteButtons();
ShowSaveResetCancelButtons();
UnlockInputs();
PriceInput.IsReadOnly = false;
OechsleInput.IsReadOnly = false;
InitInputs();
FillInputs(new Graph(GraphList.Items.Count + 1, MinOechsle, MaxOechsle));
EnableOptionButtons();
}
private void EditButton_Click(object sender, RoutedEventArgs e) {
if (GraphList.SelectedItem == null) {
return;
}
IsEditing = true;
GraphList.IsEnabled = false;
HideNewEditDeleteButtons();
ShowSaveResetCancelButtons();
UnlockInputs();
PriceInput.IsReadOnly = false;
OechsleInput.IsReadOnly = false;
if (PrimaryMarkedPointIndex != -1) EnableActionButtons();
}
private async void DeleteButton_Click(object sender, RoutedEventArgs e) {
Graph g = (Graph)GraphList.SelectedItem;
if (g == null) return;
var r = MessageBox.Show(
$"Soll der Graph {g.Num} (verwendet in folgenden Verträgen: {g.Contracts}) wirklich unwiderruflich gelöscht werden?",
"Graph löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
if (r == MessageBoxResult.Yes) {
bool success = await RemoveGraph(g.Num);
if (!success) {
MessageBox.Show("Der Graph konnte nicht gelöscht werden", "Graph löschen", MessageBoxButton.OK, MessageBoxImage.Error);
}
await RefreshGraphList();
}
}
private async void SaveButton_Click(object sender, RoutedEventArgs e) {
int? index = await UpdateGraph(Graph);
if (index == null) {
MessageBox.Show("Der Graph konnte nicht gespeichert werden", "Graph speichern", MessageBoxButton.OK, MessageBoxImage.Error);
}
IsEditing = false;
IsCreating = false;
GraphList.IsEnabled = true;
HideSaveResetCancelButtons();
ShowNewEditDeleteButtons();
LockInputs();
PriceInput.IsReadOnly = true;
OechsleInput.IsReadOnly = true;
await RefreshGraphList();
GraphList.SelectedIndex = index.Value;
}
private async Task<int?> UpdateGraph(Graph g) {
List<PaymentVar> paymentVars = await Context.PaymentVariants.Where(p => p.Year == Year && p.AvNr == AvNr).ToListAsync();
if (paymentVars.Count != 1) {
return null;
}
PaymentVar paymentVar = paymentVars[0];
var data = JsonNode.Parse(paymentVar.Data).AsObject();
var auszahlungsSorten = data["AuszahlungSorten"];
if (auszahlungsSorten == null) {
return null;
}
var Graphs = auszahlungsSorten["Kurven"].AsArray();
if (Graphs == null) {
return null;
}
if (IsEditing) {
Graphs[g.Num - 1] = g.ToJson();
} else if(IsCreating) {
Graphs.Add(g.ToJson());
} else {
return null;
}
EntityEntry<PaymentVar>? tr = null;
try {
paymentVar.Data = data.ToString();
tr = Context.Update(paymentVar);
await Context.SaveChangesAsync();
} catch (Exception exc) {
if (tr != null) await tr.ReloadAsync();
var str = "Der Eintrag konnte nicht in der Datenbank gelöscht werden!\n\n" + exc.Message;
if (exc.InnerException != null) str += "\n\n" + exc.InnerException.Message;
MessageBox.Show(str, "Graph löschen", MessageBoxButton.OK, MessageBoxImage.Error);
}
return g.Num - 1;
}
private void ResetButton_Click(object sender, RoutedEventArgs e) {
if (IsEditing) {
RefreshInputs();
} else if (IsCreating) {
InitInputs();
}
UpdateButtons();
}
private void CancelButton_Click(object sender, RoutedEventArgs e) {
IsEditing = false;
IsCreating = false;
GraphList.IsEnabled = true;
HideSaveResetCancelButtons();
ShowNewEditDeleteButtons();
DisableActionButtons();
RefreshInputs();
PriceInput.Text = "";
OechsleInput.Text = "";
ClearInputStates();
LockInputs();
PriceInput.IsReadOnly = true;
OechsleInput.IsReadOnly = true;
}
private void GraphList_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) {
RefreshInputs();
//var x = OechslePricePlot.Plot.GetPlottables().OfType<ScatterPlot>();
//MessageBox.Show($"SelectionChanged\nLength: {x.ToList().Count}, Ys: {string.Join(", ", ((ScatterPlot)x.First()).Ys)}");
}
private void PriceInput_LostFocus(object sender, RoutedEventArgs e) {
}
private void OechsleInput_LostFocus(object sender, RoutedEventArgs e) {
}
private void GraphNumberInput_TextChanged(object sender, TextChangedEventArgs e) {
}
private void GraphNumberInput_LostFocus(object sender, RoutedEventArgs e) {
}
}
}