Search code examples
c#wpflivecharts

Change in collection won't update LiveCharts plot


Changes in MainWindows.xaml.cs DropImages won't update LiveCharts, meaning that after initializing dropPhotos1 in public MainWindow(), changes from ChooseReference_OnClick(object sender, RoutedEventArgs e) won't affect plot despite the fact that values from scatterplot.xaml.cs get updated. I have MainWindow.xaml.cs:

namespace DDrop
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        ObservableCollection<DropPhoto> DropImages = new ObservableCollection<DropPhoto>();

        public static readonly DependencyProperty dropPhotos1Property =
            DependencyProperty.Register("dropPhotos1", typeof(ObservableCollection<DropPhoto>), typeof(MainWindow), new FrameworkPropertyMetadata(null));

    ObservableCollection<DropPhoto> dropPhotos1
    {
        get { return (ObservableCollection<DropPhoto>)GetValue(dropPhotos1Property); }
        set { SetValue(dropPhotos1Property, value); }
    }
    public MainWindow()
    {           
        InitializeComponent();
        Photos.ItemsSource = DropImages;
        dropPhotos1 = DropImages;
    }

    private void ChooseReference_OnClick(object sender, RoutedEventArgs e)
    {
        OpenFileDialog openFileDialog = new OpenFileDialog();

        openFileDialog.Filter = "Jpeg files (*.jpg)|*.jpg|All files (*.*)|*.*";
        openFileDialog.Multiselect = false;
        openFileDialog.AddExtension = true;
        if (openFileDialog.ShowDialog() == true)
        {
            Properties.Settings.Default.Reference = openFileDialog.FileName;
            ReferenceImage.Source = new BitmapImage(new Uri(openFileDialog.FileName));
        }

        DropImages.Add(new DropPhoto
        {
            Drop = new Drop()
            {
                RadiusInMeters = 11
            }
        });
    }
}

I imported plot user control into MainWindow.Xaml:

<uc:ScatterPlot VovaPhotos = "{Binding dropPhotos1, ElementName=myWindow}"/>

scatter plot xaml:

<UserControl x:Class="DDrop.Controls.ScatterPlot"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:DDrop.Controls"
             xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300" d:DataContext="{d:DesignInstance local:ScatterPlot}">
    <Grid>
        <lvc:CartesianChart Name="а" Series="{Binding SeriesCollection}" LegendLocation="Right" >
            <lvc:CartesianChart.AxisY>
                <lvc:Axis Title="Радиус, м" LabelFormatter="{Binding YFormatter}"></lvc:Axis>
            </lvc:CartesianChart.AxisY>
            <lvc:CartesianChart.AxisX>
                <lvc:Axis Title="Время, с"  Labels="{Binding Labels}"></lvc:Axis>
            </lvc:CartesianChart.AxisX>
        </lvc:CartesianChart>
    </Grid>
</UserControl>

scatterplot.xaml.cs:

namespace DDrop.Controls
{
    /// <summary>
    /// Логика взаимодействия для UserControl1.xaml
    /// </summary>
    public partial class ScatterPlot : UserControl
    {
        public static readonly DependencyProperty VovaProperty =
        DependencyProperty.Register("VovaPhotos", typeof(ObservableCollection<DropPhoto>), typeof(ScatterPlot));

        public ObservableCollection<DropPhoto> VovaPhotos
        {
            get { return (ObservableCollection<DropPhoto>)GetValue(VovaProperty); }
            set { SetValue(VovaProperty, value); }
        }
        public ScatterPlot()
        {
            InitializeComponent();

            if (DesignerProperties.GetIsInDesignMode(this))
            {
                return;
            }

            Loaded += SudokuUniGrid_Loaded;
        }

        private void SudokuUniGrid_Loaded(object sender, RoutedEventArgs e)
        {

            ChartValues<double> values = new ChartValues<double>();

            foreach (var dropPhoto in VovaPhotos)
            {
                values.Add(dropPhoto.Drop.RadiusInMeters);
            }

            SeriesCollection = new SeriesCollection
            {
                new LineSeries
                {
                    Title = "Series 1",
                    Values = values,
                    LineSmoothness = 0, //0: straight lines, 1: really smooth lines
                    PointGeometry = Geometry.Parse("m 25 70.36218 20 -28 -20 22 -8 -6 z"),
                    PointGeometrySize = 50,
                    PointForeground = Brushes.Gray
                },
            };

            Labels = new[] { "Jan", "Feb", "Mar", "Apr", "May" };
            YFormatter = value => value.ToString("C");
            а.Update();
            DataContext = this;
        }

        public SeriesCollection SeriesCollection { get; set; }
        public string[] Labels { get; set; }
        public Func<double, string> YFormatter { get; set; }
    }
}

DropPhoto model:

using System.ComponentModel;

namespace DDrop.BE.Models
{
    public class DropPhoto : INotifyPropertyChanged
    {
        private Drop _drop;
        public Drop Drop
        {
            get
            {
                return _drop;
            }
            set
            {
                _drop = value;
                OnPropertyChanged(new PropertyChangedEventArgs("Drop"));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            PropertyChanged?.Invoke(this, e);
        }
    }
}

Drop model:

using System;
using System.ComponentModel;

namespace DDrop.BE.Models
{
    public class Drop : INotifyPropertyChanged
    {
        private double _radiusInMeters;
        public double RadiusInMeters
        {
            get
            {
                return _radiusInMeters;
            }
            set
            {
                _radiusInMeters = value;
                OnPropertyChanged(new PropertyChangedEventArgs("RadiusInMeters"));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            PropertyChanged?.Invoke(this, e);
        }
    }
}

enter image description here


Solution

  • I managed to do update them, by implementing INotifyPropertyChanged

        using DDrop.BE.Models;
        using LiveCharts;
        using LiveCharts.Wpf;
        using System;
        using System.Collections.Generic;
        using System.Collections.ObjectModel;
        using System.ComponentModel;
        using System.Windows;
        using System.Windows.Controls;
        using System.Windows.Media;
    
        namespace DDrop.Controls
        {
            /// <summary>
            /// Логика взаимодействия для UserControl1.xaml
            /// </summary>
            public partial class ScatterPlot : UserControl, INotifyPropertyChanged
            {
                public static readonly DependencyProperty VovaProperty =
                DependencyProperty.Register("VovaPhotos", typeof(ObservableCollection<DropPhoto>), typeof(ScatterPlot));
    
                public ObservableCollection<DropPhoto> VovaPhotos
                {
                    get { return (ObservableCollection<DropPhoto>)GetValue(VovaProperty); }
                    set { SetValue(VovaProperty, value); OnPropertyChanged(new PropertyChangedEventArgs("VovaPhotos")); }
                }
                public ScatterPlot()
                {
                    InitializeComponent();
    
                    if (DesignerProperties.GetIsInDesignMode(this))
                    {
                        return;
                    }
    
                    Loaded += SudokuUniGrid_Loaded;
                }
    
                private void SudokuUniGrid_Loaded(object sender, RoutedEventArgs e)
                {
                    ChartValues<double> values = new ChartValues<double>();
    
                    foreach (var dropPhoto in VovaPhotos)
                    {
                        values.Add(dropPhoto.Drop.RadiusInMeters);
                    }
    
                    SeriesCollection = new SeriesCollection
                    {
                        new LineSeries
                        {
                            Title = "Series 1",
                            Values = values,
                            LineSmoothness = 0, //0: straight lines, 1: really smooth lines
                            PointGeometry = Geometry.Parse("m 25 70.36218 20 -28 -20 22 -8 -6 z"),
                            PointGeometrySize = 50,
                            PointForeground = Brushes.Gray
                        },
                    };
    
                    Labels = new[] { "Jan", "Feb", "Mar", "Apr", "May" };
                    YFormatter = value => value.ToString("C");
                    а.Update();
                    DataContext = this;
                }
                private SeriesCollection _series;
                public SeriesCollection SeriesCollection
                {
                    get
                    {
                        return _series;
                    }
                    set
                    {
                        _series = value;
                        OnPropertyChanged(new PropertyChangedEventArgs("SeriesCollection"));
                    }
                }
    
                public string[] Labels { get; set; }
                public Func<double, string> YFormatter { get; set; }
    
                public event PropertyChangedEventHandler PropertyChanged;
    
                public void OnPropertyChanged(PropertyChangedEventArgs e)
                {
                    PropertyChanged?.Invoke(this, e);
                }
            }
        }