简体   繁体   中英

Realtime UI and LiveCharts update in MVVM

I'm trying to implement a real-time plot UI, i'm using WPF with the MVVM Pattern and Live-Charts by beto-rodriguez as my plot library, but i have some trouble with updating the graphs in real time. I know that i have to run multiple threads to update the UI in realtime, but every single way i tried doesn't work (i'm learning C# now). I'm confused of how i should properly implement this pattern for the realtime update, and if the plot library is able to do that.

This is my actual code (its a simplified version of what i will do and doesn't implement any multithread 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;
                }
            }
        }
    }

Here is the View 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();
        }
    }
}

And the 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] [ 在此处输入图片说明 ] 1

Your XFormatter & YFormatter should both be like this:

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

If you are using C#6 you should do nameof(YFormatter) instead.

That will cause the view to update, otherwise the view has no way of knowing that the formatter changed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM