2016-03-22 7 views
1

Ich versuche, eine Echtzeit-Plot UI zu implementieren, ich benutze WPF mit dem MVVM Pattern und Live-Charts von BeTO-Rodriguez als meine Plot-Bibliothek, aber ich habe einige Probleme mit dem Aktualisieren der Graphen in Echtzeit. Ich weiß, dass ich mehrere Threads ausführen muss, um die Benutzeroberfläche in Echtzeit zu aktualisieren, aber jede einzelne Methode, die ich ausprobiert habe, funktioniert nicht (ich lerne jetzt C#). Ich bin verwirrt, wie ich dieses Muster für das Echtzeit-Update richtig implementieren sollte, und ob die Plot-Bibliothek dazu in der Lage ist.Echtzeit UI und LiveCharts Update in MVVM

Dies ist mein eigentlicher Code (es ist eine vereinfachte Version von dem, was ich tue und implementieren keinen Multi-Thread-Code)

Modelview-Code:

using System; 
using System.ComponentModel; 
using System.Windows; 
using LiveCharts; 


    namespace TestMotionDetection 
    { 
     class MainViewModel : INotifyPropertyChanged 
     { 
      public SeriesCollection Series { get; set; } 

      public Func<double, string> YFormatter { get; set; } 
      public Func<double, string> XFormatter { get; set; } 

      public DataViewModel SData 
      { 
       set 
       { 
        Series[0].Values.Add(value); 
        OnPropertyChanged("Series"); 
       } 
      } 

      public event PropertyChangedEventHandler PropertyChanged; 

      public MainViewModel() 
      { 
       SeriesConfiguration<DataViewModel> config = new SeriesConfiguration<DataViewModel>(); 
       config.Y(model => model.Value); 
       config.X(model => model.Time); 

       Series = new SeriesCollection(config) 
       { 
        new LineSeries {Values = new ChartValues<DataViewModel>(), PointRadius = 0} 
       }; 

       XFormatter = val => Math.Round(val) + " ms"; 
       YFormatter = val => Math.Round(val) + " °"; 
      } 

      protected virtual void OnPropertyChanged(string propertyName) 
      { 
       PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
      } 

      public void generateData() 
      { 
       DataViewModel val = new DataViewModel(); 
       for (int i = 0; i < 500; i++) 
       { 
        val.Time = i; 
        val.Value = i + 2.3f; 
        SData = val; 
       } 
      } 
     } 
    } 

Hier ist die Ansicht Code:

using System.Windows; 


namespace TestMotionDetection 
{ 
    /// <summary> 
    /// Logica di interazione per MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     private MainViewModel vista; 

     public MainWindow() 
     { 
      vista = new MainViewModel(); 
      DataContext = vista; 
     } 

     private void button_Click(object sender, RoutedEventArgs e) 
     { 
      vista.generateData(); 
     } 
    } 
} 

Und die XALM:

<Window x:Class="TestMotionDetection.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:lvc="clr-namespace:LiveCharts;assembly=LiveCharts" 
     Title="Example 2 (WPF)" 
     Width="1025.213" 
     Height="482.801"> 

    <Grid> 
     <lvc:LineChart Margin="0,2,245,-2" 
         LegendLocation="Right" 
         Series="{Binding Series}"> 
      <lvc:LineChart.AxisX> 
       <lvc:Axis LabelFormatter="{Binding XFormatter}" Separator="{x:Static lvc:DefaultAxes.CleanSeparator}" /> 
      </lvc:LineChart.AxisX> 
      <lvc:LineChart.AxisY> 
       <lvc:Axis LabelFormatter="{Binding YFormatter}" /> 
      </lvc:LineChart.AxisY> 
     </lvc:LineChart> 
     <Button x:Name="button" 
       Width="151" 
       Height="79" 
       Margin="804,47,0,0" 
       HorizontalAlignment="Left" 
       VerticalAlignment="Top" 
       Click="button_Click" 
       Content="Button" /> 
    </Grid> 
</Window> 

[UPDATE 1] [enter image description here] 1

+0

Sie brauchen keine Multi Threading für Live-Charts zu arbeiten, bitte, wenn Sie einen Issue Conciser haben, melden Sie es an die Gitbug Repo https://github.com/beto-rodriguez/Live-Charts –

Antwort

1

Ihre XFormatter & YFormatter beide sollten so aussehen:

private Func<double, string> _yFormatter; 
public Func<double, string> YFormatter { 
    get{ return _yFormatter; } 
    set 
    { 
     _yFormatter = value; 
     OnPropertyChanged("YFormatter"); 
    } 

Wenn Sie C# 6 verwenden Sie nameof(YFormatter) stattdessen tun sollten.

Das wird dazu führen, dass die Ansicht aktualisiert wird, ansonsten kann die Ansicht nicht erkennen, dass sich der Formatierer geändert hat.

+0

Das Problem ist nicht der Formatierer, in meiner "Haupt" -Implementierung aktualisiert das Diagramm eine Sekunde, nachdem der Datenstrom endet, ohne dass ich die Formatiererwerte ändere. Ich füge nur neue Daten in die Serie ein. –

+0

Wenn sich Ihre Formatierungen nie ändern, hängt das Problem wahrscheinlich mit Live-Charts zusammen ... von einem Teil des Codes, den Sie hier nicht angegeben haben. Alles andere sieht vom MVVM-Standpunkt gut aus. Ich würde empfehlen, dass Sie Live-Charts zu Ihren Tags hinzufügen und/oder diese Frage in ihre Foren stellen. –

+0

... Oder Sie müssen 'OnPropertyChanged (" YFormatter ");' jedes Mal aufrufen, wenn Sie der Serie ein Element hinzufügen. –