具有动态系列数的Sf笛卡尔图表

问题描述 投票:0回答:1

我正在尝试使用 SfCartesianChart(版本 22.2.12)在 dotnet maui 中显示动态数量的系列。

图表中的所有数据都存在于 ViewModel 中,如下所示:

public class ChartPageViewModel : BaseViewModel, IChartPageViewModel
{
    //Data are loaded asynchronously after the page load
    //after setting the data the PropertyChangedEvent is fired
    public ObservableCollection<IChartSeriesViewModel> DataSeries { get; set; }
}

public class ChartSeriesViewModel : IChartSeriesViewModel
{
    public string Title { get; set; }
    public IList<IChartPointViewModel> Data { get; set; }
}
    
public class ChartPointViewModel : IChartPointViewModel
{
    public DateTime Date { get; set; }
    public decimal Value { get; set; }
}

使用值转换器将数据与系列属性绑定:

<chart:SfCartesianChart Series="{Binding DataSeries, Converter={StaticResource DataSeriesConverter}}">
     <chart:SfCartesianChart.XAxes>
         <chart:CategoryAxis />
     </chart:SfCartesianChart.XAxes>
     <chart:SfCartesianChart.YAxes>
         <chart:NumericalAxis />
     </chart:SfCartesianChart.YAxes>
 </chart:SfCartesianChart>

值转换器(IList 到 ChartSeriesCollection)

public class SfCartesianChartDataSeriesConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is IList<IChartSeriesViewModel> chartSeries)
        {
            ChartSeriesCollection series = new ChartSeriesCollection();

            foreach (var i in chartSeries)
            {
                series.Add(new FastLineSeries()
                {
                    ItemsSource = i.Data,
                    XBindingPath = nameof(IChartPointViewModel.Date),
                    YBindingPath = nameof(IChartPointViewModel.Value),
                });
            }

            return series;
        }

        return null;
    }

不幸的是,数据仅在重绘视图时显示/绘制(例如,调整窗口大小)。

PropertyChangedEvent 似乎工作正常,因为当我在 xaml 中添加一系列数据时,数据会在 PropertyChangedEvent 之后立即显示。

<chart:SfCartesianChart>
    <chart:SfCartesianChart.XAxes>
        <chart:CategoryAxis />
    </chart:SfCartesianChart.XAxes>
    <chart:SfCartesianChart.YAxes>
        <chart:NumericalAxis />
    </chart:SfCartesianChart.YAxes>

    <chart:FastLineSeries
           ItemsSource="{Binding DataSeries[0].Data}"
           XBindingPath="Date"
           YBindingPath="Value" />
</chart:SfCartesianChart>

但这不是创建动态数量系列的方法。

如何强制“重画”? 或者这种情况应该如何绑定?

.net maui syncfusion syncfusion-chart
1个回答
0
投票

已根据您的输入准备了样本。这一要求已通过扩展 CartesianChart 来实现。下面附上示例供参考。

公共类 CartesianExt :SfCartesianChart

{

    public static readonly BindableProperty SeriesCollectionProperty = BindableProperty.Create("SeriesCollection", typeof(ObservableCollection<IChartSeriesViewModel>), typeof(CartesianExt), null, BindingMode.Default, null, OnSeriesPropertyChanged);



    public ObservableCollection<IChartSeriesViewModel> SeriesCollection

    {

        get

        {

            return (ObservableCollection<IChartSeriesViewModel>)GetValue(SeriesCollectionProperty);

        }

        set { SetValue(SeriesCollectionProperty, value);}

    }





    private static void OnSeriesPropertyChanged(BindableObject bindable, object oldValue, object newValue)

    {

        (bindable as CartesianExt).GenerateSeries(newValue);

    }



    private void GenerateSeries(object newValue)

    {

       if(newValue is ObservableCollection<IChartSeriesViewModel> collection)

       {              

            if (newValue is INotifyCollectionChanged)

                (newValue as INotifyCollectionChanged).CollectionChanged += DataPoint_CollectionChanged;

           foreach(var item in collection)

            {

                CreateSeries(item);

            }

        }



    }



    private void CreateSeries(IChartSeriesViewModel item)

    {

        FastLineSeries series = new FastLineSeries()

        {

            ItemsSource = item.LiveData,

            XBindingPath = nameof(IChartPointViewModel.Date),

            YBindingPath = nameof(IChartPointViewModel.Value),

        };

        Series.Add(series);



    }



    private void DataPoint_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)

    {

        switch (e.Action)

        {

            case NotifyCollectionChangedAction.Add:

                CreateSeries(e.NewItems[0] as IChartSeriesViewModel);

                break;

            case NotifyCollectionChangedAction.Remove:

                Series.RemoveAt(e.OldStartingIndex);

                break;

        }



    }

    }

公共 ChartSeriesViewModel()

{

   

    LiveData = new ObservableCollection<IChartPointViewModel>();

    for (int i = 0; i < 100; i++)

    {

        LiveData.Add(new ChartPointViewModel() { Date = new DateTime(2005, 04, 02).AddMonths(i), Value = new Random().Next(0, 1000) });

    }

}

公共类 ChartPageViewModel:ChartSeriesViewModel

{

public ObservableCollection<IChartSeriesViewModel> DataSeries { get; set; }





public ChartPageViewModel()

{

    DataSeries=new ObservableCollection<IChartSeriesViewModel>();

    DataSeries.Add(new ChartSeriesViewModel());

}

}

    <local:CartesianExt SeriesCollection="{Binding DataSeries}" x:Name="Chart" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">

    <chart:SfCartesianChart.XAxes>

        <chart:CategoryAxis/>

    </chart:SfCartesianChart.XAxes>

    <chart:SfCartesianChart.YAxes>

        <chart:NumericalAxis/>

    </chart:SfCartesianChart.YAxes>

</local:CartesianExt>

    <Button Text="DynamicList" Clicked="Button_Clicked"></Button>

</VerticalStackLayout>

private void Button_Clicked(对象发送者,EventArgs e)

{

    chartPageViewModel.DataSeries.Add(new ChartSeriesViewModel());

}

Output

© www.soinside.com 2019 - 2024. All rights reserved.