【发布时间】:2019-06-07 08:19:34
【问题描述】:
我一直致力于在 UWP 中构建一个程序,该程序利用 Telerik Charting 控件向用户显示传入数据。在我最新的测试中,在图表上动态接收和绘制未经请求的数据,我遇到了一个未处理的异常 (NullReferenceException) 正在发生。这似乎只发生在用户将鼠标悬停在图表上且图表显示轨迹球信息(Telerik 的 ChartTrackBallBehavior)时。如果用户的鼠标在其他地方或没有触发轨迹球信息显示在图表上,则永远不会出现此异常。
到目前为止,我已经设法将 NullException 跟踪到发生在 Telerik UWP UI 中 ChartTrackBallBehavior.cs 中的函数 GetIntersectionTemplate() 内。除此之外,我不知道我能做些什么来解决这个问题,以免它再次发生。
这是发生异常时的典型堆栈跟踪:
System.ArgumentNullException: Value cannot be null.
at Telerik.UI.Xaml.Controls.Chart.ChartTrackBallBehavior.GetIntersectionTemplate(DependencyObject instance)
at Telerik.UI.Xaml.Controls.Chart.ChartTrackBallBehavior.UpdateIntersectionPoints(ChartDataContext context)
at Telerik.UI.Xaml.Controls.Chart.ChartTrackBallBehavior.UpdateVisuals()
at Telerik.UI.Xaml.Controls.Chart.RadChartBase.NotifyUIUpdated()
at Telerik.UI.Xaml.Controls.Chart.PresenterBase.UpdateUI(ChartLayoutContext context)
我尝试在将每个系列添加到图表之前和之后禁用 ChartTrackBallBehavior,但无济于事。 我尝试手动将焦点更改为图表以外的其他控件,但无济于事。 我已尝试在不同区域手动调用 Chart.UpdateLayout(),但结果是这些调用在同一位置 (ChartTrackBallBehavior.cs) 内创建了相同的 NullReferenceException。
问题的核心似乎是这个“值”被错误地设置为 null。到目前为止,我还无法确定将什么“值”设置为 null,我只能假设它在 GetIntersectionTemplate() 函数调用中遇到 NullReferenceException throw() 调用。但我不知道为什么会这样,也不知道我能做些什么。
我制作了一个最小的项目来复制问题。请注意,它会在重新绘制图表上的所有系列之前清除图表中的所有系列。这样做是为了等同于我自己的项目,并且似乎与问题本身有关。这个系列清除和重新添加过程是因为用户可以随时更改要在图表上显示的系列。
我可能可以更改编码结构以从不同的方向解决此问题,但目前我想更好地了解导致此问题的原因并尽可能解决它,否则我可能需要重写大部分代码,不幸的是,时间不在我这边。
这里是示例代码。请注意,我为此代码使用 Telerik.UI.for.UniversalWindowsPlatform 版本 1.0.1.5。
MainPage.xaml
<Page
x:Class="ExceptionReplicator.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ExceptionReplicator"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:telerikChart="using:Telerik.UI.Xaml.Controls.Chart"
xmlns:telerikPrimitives="using:Telerik.UI.Xaml.Controls.Primitives"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<telerikChart:RadCartesianChart x:Name="MainChart" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10,10,10,10">
<telerikChart:RadCartesianChart.Grid>
<telerikChart:CartesianChartGrid MajorLinesVisibility="XY"/>
</telerikChart:RadCartesianChart.Grid>
<telerikChart:RadCartesianChart.Behaviors>
<telerikChart:ChartPanAndZoomBehavior ZoomMode="Both" PanMode="Both"/>
<telerikChart:ChartTrackBallBehavior x:Name="TrackBallBehaviour" InfoMode="Multiple" ShowIntersectionPoints="True">
<telerikChart:ChartTrackBallBehavior.LineStyle>
<Style TargetType="Polyline">
<Setter Property="Stroke" Value="Tomato"/>
<Setter Property="StrokeThickness" Value="2"/>
<Setter Property="StrokeDashArray" Value="1,2"/>
</Style>
</telerikChart:ChartTrackBallBehavior.LineStyle>
<telerikChart:ChartTrackBallBehavior.IntersectionTemplate>
<DataTemplate>
<Ellipse Width="10" Height="10" Fill="Tomato"/>
</DataTemplate>
</telerikChart:ChartTrackBallBehavior.IntersectionTemplate>
</telerikChart:ChartTrackBallBehavior>
</telerikChart:RadCartesianChart.Behaviors>
<telerikChart:RadCartesianChart.VerticalAxis>
<telerikChart:LinearAxis x:Name="Vertical" Title="Y Axis" Minimum="0"/>
</telerikChart:RadCartesianChart.VerticalAxis>
<telerikChart:RadCartesianChart.HorizontalAxis>
<telerikChart:LinearAxis x:Name="Horizontal" Title="X Axis"/>
</telerikChart:RadCartesianChart.HorizontalAxis>
</telerikChart:RadCartesianChart>
</Grid>
</Page>
MainPage.xaml.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
namespace ExceptionReplicator
{
using System;
using System.Threading;
using Telerik.UI.Xaml.Controls.Chart;
using Windows.UI.Core;
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
private Timer DataTimer; // timer to periodically add data to the chart
private int LineCount = 1; // arbitrary line counter to differentiate lines from each other
// custom class for holding the data to be displayed on the chart
private class Data
{
public int XValue { get; set; }
public int YValue { get; set; }
}
// overarching class that holds all of the data for ONE line/series
private class DataToChart
{
// List of all the data points within this instance of DataToChart
public List<Data> DataPoints;
// Constructor to initialise DataPoints
public DataToChart()
{
DataPoints = new List<Data>();
}
}
// Overarching container to hold data for ALL lines/series
private List<DataToChart> allData = new List<DataToChart>();
public MainPage()
{
this.InitializeComponent();
// set up the timer to call every 10s to add new data to the chart. warning: this will run infinitely
DataTimer = new Timer(DataCallback, null, (int)TimeSpan.FromSeconds(10).TotalMilliseconds, Timeout.Infinite);
}
// Generic callback to call AddLineToChart() on the other thread to handle the Chart's data
private void DataCallback(object state)
{
var task = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => AddLineToChart());
}
// Code to handle adding a line to the chart
private void AddLineToChart()
{
// Using Random() to create random data
Random rand = new Random();
DataToChart dataToChart = new DataToChart();
for (int i = 0; i < 50; i++)
{
dataToChart.DataPoints.Add(new Data
{
XValue = i,
YValue = rand.Next(0, 100)
});
}
// Add the data for this line/series to the overarching container
allData.Add(dataToChart);
// re-initialise the line count
LineCount = 1;
// Currently the code needs to clear the chart and redraw it each time new data is introduced
MainChart.Series.Clear();
// For each line/series in the main container
foreach (DataToChart data in allData)
{
// Make a series for the line
ScatterLineSeries scatterLineSeries = new ScatterLineSeries
{
Name = $"Line {LineCount}",
ItemsSource = dataToChart.DataPoints,
XValueBinding = new PropertyNameDataPointBinding("XValue"),
YValueBinding = new PropertyNameDataPointBinding("YValue"),
DisplayName = $"Line {LineCount}",
LegendTitle = $"Line {LineCount}",
};
// Add the line to the Chart's Series collection
MainChart.Series.Add(scatterLineSeries);
// Increment arbitrary counter
LineCount++;
}
// Re-set the timer to fire again in 10s
DataTimer.Change((int)TimeSpan.FromSeconds(10).TotalMilliseconds, Timeout.Infinite);
}
}
}
我需要找到一种解决方案,以确保在引入新数据时不再出现此异常。任何帮助将不胜感激。
在短期内,我已经从我的图表中完全删除了 ChartTrackBallBehavior(已将其注释掉),直到我确定解决方案为止。移除 Behavior 后,不会发生此异常。
【问题讨论】:
标签: c# xaml charts uwp telerik