microcharts-dotnet / Microcharts

Create cross-platform (Xamarin, Windows, ...) simple charts.
MIT License
2.01k stars 360 forks source link

[Question] Usage Help. Updating chart does not remove previous chart unless resizing the screen #363

Open PickleBurg opened 1 month ago

PickleBurg commented 1 month ago

I have encountered an interesting issue while attempting to create a line chart that I expect to update every second with a new value.

this does work and renders on the screen. the issue I have is when I notify a property change the new chart shows but the old ones does not disappear unless I resize the window of the application.

using CommunityToolkit.Mvvm.ComponentModel;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Maui.Dispatching;
using Microcharts;

namespace ImageSource_Memory_Leak
{
    public partial class MainPageViewModel : ObservableObject
    {
        private readonly Random _random;

        public MainPageViewModel()
        {
            _random = new Random();
            MyChart = CreateInitialChart();
            PollValuesAsync();
        }

        private LineChart CreateInitialChart()
        {
            return new LineChart
            {
                Entries = GenerateRandomBpmData(),
                LineMode = LineMode.Straight,
                PointMode = PointMode.Circle,
                LabelTextSize = 20,
                LineSize = 4,
                BackgroundColor = SKColors.Transparent
            };
        }

        private List<ChartEntry> GenerateRandomBpmData()
        {
            float bpm = GenerateRandomBpm();
            string label = DateTime.Now.ToString(@"mm\:ss");

            return new List<ChartEntry>
            {
                new ChartEntry(bpm)
                {
                    Color = SKColor.Parse("#FF1493"),
                    Label = label,
                    ValueLabel = bpm.ToString()
                }
            };
        }

        private float GenerateRandomBpm() => _random.Next(60, 120);

        [ObservableProperty]
        private LineChart myChart;

        private async Task PollValuesAsync()
        {
            var entries = MyChart.Entries.ToList();

            while (true)
            {
                await Task.Delay(1000);

                float bpm = GenerateRandomBpm();
                string label = DateTime.Now.ToString(@"mm\:ss");

                entries.Add(new ChartEntry(bpm)
                {
                    Color = SKColor.Parse("#FF1493"),
                    Label = label,
                    ValueLabel = bpm.ToString()
                });

                MyChart = new LineChart
                {
                    Entries = entries,
                    LineMode = LineMode.Straight,
                    PointMode = PointMode.Circle,
                    LabelTextSize = 20,
                    LineSize = 4,
                    BackgroundColor = SKColors.Transparent,
                    IsAnimated = false,
                };

            }
        }
    }
}

https://github.com/PickleBurg/ImageSource-Memory-Leak/tree/chart-stuff

code repo for anyone interested.

image It starts to increase in the amout of charts present

image Them i resize andd it shows less.

<charts:ChartView x:Name="ChartView"
                  Chart="{Binding MyChart}"
                  VerticalOptions="FillAndExpand"
                  HorizontalOptions="FillAndExpand" />
YBTopaz8 commented 1 week ago

Same issue. I thought I was crazy lol Sadly no solution yet

YBTopaz8 commented 1 week ago

I got one solution working (or at least a workaround) tested on Donut Charts and line charts (probably works on all) So Here is what I do;

private async void TapGestureRecognizer_Tapped(object sender, TappedEventArgs e)
 {
     var send = (FlexLayout)sender;
     var song = send.BindingContext as SingleSongStatistics;
     if (song is null)
     {
         return;
     }
     HomePageVM.ShowSingleSongStatsCommand.Execute(song.Song); // method to update chart
     LineChartBor.WidthRequest = LineChartBor.Width + 1;  //LineChartBor is the border that has my chart
     await Task.Delay(250);
     LineChartBor.WidthRequest = LineChartBor.Width - 1;

 }

My XAML looks like this

<Border x:Name="LineChartBor" HeightRequest="400"
        Stroke="DarkSlateBlue"
        StrokeShape="RoundRectangle 15">
    <mc:ChartView Chart="{Binding LChart}"                              
                  />

</Border>

Hope that helps !

PickleBurg commented 1 week ago

I'm definitely going to give this a go I'll let you know!!