GithubHelp home page GithubHelp logo

Comments (9)

aloisdeniel avatar aloisdeniel commented on August 23, 2024 6

Hi!

Doable, but you have to update the entire Chart value and you can't change each independent sub-value at the moment.

You juste have to update the Chart property of the ChartView, for example from a binding in Xamarin.Forms.

View

<microcharts:ChartView Chart="{Binding Chart}" />

ViewModel

public Chart Chart { get; private set; }

private async Task PollValuesAsync()
{
   while(true)
  {
    await Task.Delay(1000);
    var values = await this.myapi.GetValuesAsync();
    this.Chart = new RadialGaugeChart()
    {
        Entries = values.Select(v => new Entry(v)),
     };
     this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.Chart));
  }
}

from microcharts.

VolckaertAchiel avatar VolckaertAchiel commented on August 23, 2024 1

do you have an example for xamarin.ios?

from microcharts.

dimitrijevic avatar dimitrijevic commented on August 23, 2024

Hi @aloisdeniel ,
Is it just me, or does databinding to a Chart object cause flickering on databound updates even with IsAnimated set to true (BTW I'm trying to do this by databinding from a ViewModel and not in codebehind...so you not yet be supporting animating fast UI refreshes, or are you, would it need something of a rewrite to work better like in #46 )?
My entries come from an accelometer which I'm sampling at 40ms thus more frequently than 1000ms, but my input also probably takes a bit more longer time to be processed than your Select from the values you get from the myapi.GetValuesAsync(), so is there anything that could be used to animate that transition more smoothly?
TIA

P.S.
In page codebehind I was able to do smoother animations on a RadialGaugeChart by manually invalidating and controling the ChartView's PaintSurface event handler...but that seems like a hack to me...or is it the only was for fast UI refresh without flicker effects using Microcharts please?

from microcharts.

godrose avatar godrose commented on August 23, 2024

@aloisdeniel Great job!
Any chance the Entries property will work like an ObservableCollection?

from microcharts.

majzayer avatar majzayer commented on August 23, 2024

Hello @aloisdeniel,

I've tried the code you posted above as well as the implementation of @andreatosato in issue#46 to refresh all entries every 20ms and the visualization becomes very laggy.

I noticed that if the ChartView.Chart is triggered as changed via OnChartChanged, the canvas gets invalidated and repainted. If my understanding is correct, is there a way to avoid complete repaints as entries are updated?

from microcharts.

carlosalexandre3107 avatar carlosalexandre3107 commented on August 23, 2024

do you have an example for xamarin.ios?

Hello @VolckaertAchiel !
I still do not know if it's the best way. But this was my solution using the MVVMCross

  • I have created an instance of 'ChartView' and insert it into the screen.
  • In the 'ViewModel' that is linked to my screen. I created a property of type 'Chart' receiving the API data
    Chart = new DonutChart() { Entries = EntryChart.ToList(), LabelTextSize = 15f, }; RaisePropertyChanged(nameof(Chart));
  • Using 'MvxFluentBinding' to mount the chart on the screen
    var set = this.CreateBindingSet<MyView, MyViewModel>(); set.Bind(ChartView).For(v => v.Chart).To(vm => vm.Chart); set.Apply();

from microcharts.

Nixon-Joseph avatar Nixon-Joseph commented on August 23, 2024

Hello! I'm attempting to clean up some of these older issues that haven't had any movement for a few months, if here is still and issue or enhancement to be made, please create a new issue, and feel free to reference relevant parts of this issue if necessary.

Thanks!

from microcharts.

twofingerrightclick avatar twofingerrightclick commented on August 23, 2024

Hi!

Doable, but you have to update the entire Chart value and you can't change each independent sub-value at the moment.

You juste have to update the Chart property of the ChartView, for example from a binding in Xamarin.Forms.

View

<microcharts:ChartView Chart="{Binding Chart}" />

ViewModel

public Chart Chart { get; private set; }

private async Task PollValuesAsync()
{
   while(true)
  {
    await Task.Delay(1000);
    var values = await this.myapi.GetValuesAsync();
    this.Chart = new RadialGaugeChart()
    {
        Entries = values.Select(v => new Entry(v)),
     };
     this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.Chart));
  }
}

I have turned a line chart into a window's task manager style stat chart (like it updates every second with new data in a scrolling timeline fashion). I can get it to run on Android by just Changing the entries on the chart: Chart.Entries =newEntries ; and it will draw just fine because of luck that the UI thread is used. So I wanted to document here in this issue, that in 0.9.5.9 changing the chart entries causes a redraw (InvalidateSurface). This is nice, but it doesn't play well because you cannot control what thread the InvalidateSurface will be called from, so this doesn't work with iOS 14.3.
Also doing microcharts:ChartView Chart="{Binding Chart}" and changing the Chart (Chart= new Chart... this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.Chart));) in the viewModel doesn't work. It will result in a UIKIt error, as the property changed event handler will not necessarily run on the UI thread. This could vary by iOS version and Xamarin.Forms version. I am using 4.8.0.1687 and iOS 14.3.
I will add here how to redraw/ update a chart view when I figure out how to manage what thread InvalidateSurface is called from.

from microcharts.

twofingerrightclick avatar twofingerrightclick commented on August 23, 2024

So the offending structural set up is based around this line in ChartView.cs. The ChartView presumes properties on a chart are always being changed on the main UI thread. This is of course not always the case. Especially as in the example of data coming from a polling task.
view.handler = view.chart.ObserveInvalidate(view, (v) => v.InvalidateSurface()); at line 63 in ChartView.cs should check what thread is being run on and if not on the UI thread for Xamarin.Forms it should be Device.BeginInvokeOnMainThread(( => v.InvalidateSurface())) to make sure that the drawing occurs. The offending problem is that PlanifyInvalidate in Chart.cs is async void!!!! So you will never know why your app is crashing, when a property on a chart is changed from a thread other than the UI thread when it reaches view.handler = view.chart.ObserveInvalidate(view, (v) => v.InvalidateSurface());.

The simplest work around is make a "custom" chart by deriving from Chart, and just overriding OnPropertyChanged like so:

/// <summary>
/// Invoked whenever a property changed.
/// </summary>
/// <param name="sender">Sender.</param>
/// <param name="e">E.</param>
protected override void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    switch (e.PropertyName)
    {
        case nameof(AnimationProgress):
        case nameof(LabelTextSize):
        case nameof(MaxValue):
        case nameof(MinValue):
        case nameof(BackgroundColor):
            Device.BeginInvokeOnMainThread(() => base.OnPropertyChanged(sender, e));
            break;
        default:
            Device.BeginInvokeOnMainThread(() => base.OnPropertyChanged(sender, e));
            break;
    }
}

So that OnPropertyChanged Is ran on on the UI thread so that the await in the async void PlanifyInvalidate lets the Invalidate() be called from the UI thread.

This is not production code, as it hogs the UI thread, but as we can't get at the view.handler = view.chart.ObserveInvalidate(view, (v) => v.InvalidateSurface()); at line 63 in ChartView.cs if you are using the nuget package and not the source code, this is a working option.

from microcharts.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.