using System; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Interactivity; using System.Windows.Media; using System.Windows.Shapes; namespace WpfApp78 { public class ViewModel { public ViewModel() { SynchronizationContext sc = SynchronizationContext.Current; // UI-Thread context // asynchonously fill array vlues with data Task.Run(() => { do { Thread.Sleep(20); // 50 Hz // fill array with Y-values for (int i = 0; i <= values.GetUpperBound(0); i++) values[i] = rnd.Next(1, 300); // refresh polyline in UI thread if (CanvasView != null) sc.Post(new SendOrPostCallback(ShowValues), null); } while (true); }); } private Random rnd = new Random(); public Canvas CanvasView { get; set; } private Polyline pline = new Polyline(); private PointCollection pointCollection = new PointCollection(); private int[] values = new int[100]; public void ShowValues(object state) { if (CanvasView.Children.Count == 0) // first call, fill polyline and add to Canvas { pline.Stroke = new SolidColorBrush(Color.FromRgb(60, 125, 200)); pline.StrokeThickness = 1; pline.Points = pointCollection; for (int i = 0; i <= values.GetUpperBound(0); i++) pointCollection.Add(new Point(i * 4, values[i])); CanvasView.Children.Add(pline); } else { // write new values in polyline for (int i = 0; i <= values.GetUpperBound(0); i++) { var pt = pointCollection[i]; pt.Y = values[i]; pointCollection[i] = pt; } } } } /// /// Behavior to get Convas in ViewModel (MVVM) /// public class CanvasBehavior : Behavior { protected override void OnAttached() => AssociatedObject.Loaded += AssociatedObject_Loaded; private void AssociatedObject_Loaded(object sender, RoutedEventArgs e) => ((ViewModel)(AssociatedObject.DataContext)).CanvasView = AssociatedObject; } }