You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin.Forms SFChart加载API数据后折线图DateTime轴时间显示错误修复

Xamarin.Forms SFChart折线图DateTime轴加载数据后标签重复异常问题

问题描述

在Xamarin.Forms中使用SFChart折线图加载API响应数据时,折线图的DateTime主轴(X轴)出现时间显示错误。
当前实现使用SFChart折线图展示时序数据:

  • X轴为时间轴
  • Y轴为对应数值轴
  • 预期展示24小时连续时序数据,时间、数值字段均从API响应中提取

未加载数据时,DateTime轴显示正常:已为DateTime主轴设置IntervalType属性为Hours、Interval属性为1,预期按1小时间隔展示时间标签,未加载数据时效果如下:
未加载数据时正常显示的轴标签

加载API返回的数据后,DateTime轴时间标签出现异常重复,固定重复显示12AM、4PM、8AM等值,无法按预期生成连续的小时级时间刻度,异常效果如下:
加载数据后异常重复的轴标签

现有实现代码

页面XAML代码

<Frame HasShadow="False"
               x:Name="outframe"
               CornerRadius="{OnIdiom Phone=15,Tablet=25}"
               Padding="0"
               OutlineColor="#ffffff"
               BackgroundColor="#4A4541"
               WidthRequest="{OnIdiom Phone=320,Tablet=600}"
               HeightRequest="{OnIdiom Phone=450,Tablet=475}"
               VerticalOptions="Center"
               HorizontalOptions="Center"
               IsClippedToBounds="True">
            <StackLayout VerticalOptions="FillAndExpand"
                         HorizontalOptions="FillAndExpand" BackgroundColor="#4A4541">
                <Label Text="GRAPH"
                       FontFamily="{StaticResource PrimaryFontBold}"
                       TextColor="White"
                       VerticalTextAlignment="Center"
                       Margin="0,50,0,0"
                       HorizontalTextAlignment="Center"
                       FontSize="{OnIdiom Phone=16,Tablet=22}"
                       HorizontalOptions="Center" />

                <sfcharts:SfChart HeightRequest="200"
                                  WidthRequest="300"
                                  HorizontalOptions="CenterAndExpand"
                                  VerticalOptions="CenterAndExpand"
                                  BackgroundColor="#4A4541"
                                  AreaBorderColor="White" AreaBackgroundColor="#4A4541">

                    <sfcharts:SfChart.PrimaryAxis>
                        <sfcharts:DateTimeAxis IntervalType="Hours" Interval="1"  LabelRotationAngle="90" >
                            <sfcharts:DateTimeAxis.LabelStyle> 
                                <sfcharts:ChartAxisLabelStyle LabelFormat = "hh:mm tt" TextColor="#FDDFBD">          
                            </sfcharts:ChartAxisLabelStyle>          
                        </sfcharts:DateTimeAxis.LabelStyle>
                    </sfcharts:DateTimeAxis>
                    </sfcharts:SfChart.PrimaryAxis>

                    <sfcharts:SfChart.SecondaryAxis>
                        <sfcharts:NumericalAxis  Minimum="0"
                                                 Maximum="60"
                                                 Interval="10" >
                        <sfcharts:NumericalAxis.LabelStyle> 
                                <sfcharts:ChartAxisLabelStyle TextColor="White"> 
                            </sfcharts:ChartAxisLabelStyle>          
                        </sfcharts:NumericalAxis.LabelStyle>
                            <sfcharts:NumericalAxis.MajorGridLineStyle>
                                <sfcharts:ChartLineStyle StrokeColor="#bae1f2"/>
                            </sfcharts:NumericalAxis.MajorGridLineStyle>
                            </sfcharts:NumericalAxis>
                    </sfcharts:SfChart.SecondaryAxis>

                    <sfcharts:StackingLineSeries x:Name="MyLineChart"
                                                 XBindingPath="Key"
                                                 YBindingPath="Value" ItemsSource="{Binding LineData}"
                                                 ListenPropertyChange="True" StrokeWidth="1" Color="#FDDFBD" >
                        <sfcharts:StackingLineSeries.DataMarker>
                            <sfcharts:ChartDataMarker MarkerWidth="2" MarkerHeight="2" ShowLabel="False" ShowMarker="true" MarkerBorderColor="#bae1f2" MarkerBorderWidth="2" MarkerColor="White"/>
                        </sfcharts:StackingLineSeries.DataMarker>
                    </sfcharts:StackingLineSeries>
                </sfcharts:SfChart>
            </StackLayout>
        </Frame>

页面后台代码

RViewModel rViewModel;
public RRGraph()
{
    InitializeComponent();
    rViewModel = new RViewModel();
    BindingContext = rViewModel;
}

数据模型代码

public class ChartData
{
    public string name { get; set; }
    public ObservableCollection<LineChartData> DataPoints { get; set; }
}

public class LineChartData:INotifyPropertyChanged
{
    public LineChartData(string key, double value)
    {
        Value = value;
        Key = key;
    }

    private double value;
    public double Value
    {
        get { return value; }
        set
        {
            this.value = value;
            RaisePropertyChanged("Value");
        }
    }

    private string key;
    public string Key
    {
        get { return key; }
        set
        {
            DateTime dt = DateTime.Parse(value);
            value = dt.ToString("hh:mm tt");
            key = value;
            RaisePropertyChanged("Key");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    void RaisePropertyChanged(string name)
    {
        if (PropertyChanged != null)
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

ViewModel代码

public class RViewModel:INotifyPropertyChanged
{
    public ChartData ChartData { get; set; }
    private ObservableCollection<LineChartData> lineData;
    public ObservableCollection<LineChartData> LineData
    {
        get { return lineData; }
        set
        {
            lineData = value;
            RaisePropertyChanged(nameof(LineData));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    void RaisePropertyChanged(string name)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }

    public RViewModel(string roomId)
    {
        LoadData();
    }

    public async void LoadData()
    {
        try
        {
            //API调用逻辑
            ChartData = await AppClass.DataManager.GetRR();
            LineData = ChartData.DataPoints;
        }
        catch (Exception ex)
        {
            Crashes.TrackError(ex);
        }
    }
}

问题根因

核心问题出在数据模型的X轴字段定义上:

  • XAML中配置的主轴是DateTimeAxis,这类轴要求绑定的X值必须是DateTime类型,才能按照时间规则自动计算等间隔刻度。
  • 现有代码里X轴绑定的Key属性是字符串类型,set逻辑中还把解析出的DateTime值重新转成了hh:mm tt格式的时间字符串。图表无法将字符串识别为连续的时间维度值,只能把每个字符串当做独立分类处理,最终导致刻度生成逻辑混乱、标签重复错位。

解决方案

  1. 修改LineChartData模型,将X轴绑定字段改为DateTime类型,不要存储格式化后的字符串:
public class LineChartData:INotifyPropertyChanged
{
    public LineChartData(DateTime key, double value)
    {
        Value = value;
        Key = key;
    }

    private double value;
    public double Value
    {
        get { return value; }
        set
        {
            this.value = value;
            RaisePropertyChanged("Value");
        }
    }

    private DateTime key;
    // X轴绑定字段改为DateTime类型
    public DateTime Key
    {
        get { return key; }
        set
        {
            key = value;
            RaisePropertyChanged("Key");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    void RaisePropertyChanged(string name)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}
  1. 在API数据解析环节,将接口返回的时间字符串统一转为DateTime类型再赋值给Key属性,不要提前转成格式化字符串,轴的显示格式完全交给XAML里配置的LabelFormat = "hh:mm tt"处理即可。
  2. 加载完数据后对LineData按Key时间做一次升序排序,排查是否存在时间戳错乱、大量重复时间点的情况,避免刻度计算异常。

内容的提问来源于stack exchange,提问作者BSB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 02:51:32