绑定更新将新闻系列添加到 WPF Toolkit 图表(而不是替换/更新系列)

发布于 2024-09-05 14:35:38 字数 1667 浏览 6 评论 0原文

我目前正在我的应用程序中重新编码条形图,以利用 中的 Chart 类WPF 工具包。使用 MVVM,我将图表中 ColumnSeriesItemsSource 绑定到视图模型上的属性。以下是相关的 XAML:

<charting:Chart>
  <charting:ColumnSeries ItemsSource="{Binding ScoreDistribution.ClassScores}"
                         IndependentValuePath="ClassName" DependentValuePath="Score"/>
</charting:Chart>

以及视图模型上的属性:

// NB: viewmodel derived from Josh Smith's BindableObject
public class ExamResultsViewModel : BindableObject
{
    // ...

    private ScoreDistributionByClass _scoreDistribution;
    public ScoreDistributionByClass ScoreDistribution
    {
        get
        {
            return _scoreDistribution;
        }
        set
        {
            if (_scoreDistribution == value)
            {
                return;
            }

            _scoreDistribution = value;

            RaisePropertyChanged(() => ScoreDistribution);
        }
    }

但是,当我更新 ScoreDistribution 属性(通过将其设置为新的 ScoreDistribution 对象)时,图表会得到一个 < em>附加系列(基于新的 ScoreDistribution)以及保留原始系列(基于之前的 ScoreDistribution)。

为了说明这一点,这里有几个屏幕截图,显示更新之前的图表(在 ScoreDistribution.ClassScores 中具有单个数据点)和更新之后(现在在 ScoreDistribution.ClassScores 中具有 3 个数据点)):

使用单个数据点

添加了 2 个数据点 - 请注意它们后面的原始宽条

现在,我意识到还有其他方法可以做到这一点(例如更改原始 ScoreDistribution 对象而不是完全替换它),但我不明白为什么它当前的形式会出错。有人可以帮忙吗?

I'm currently recoding a bar chart in my app to make use of the Chart class in the WPF Toolkit. Using MVVM, I'm binding the ItemsSource of a ColumnSeries in my chart to a property on my viewmodel. Here's the relevant XAML:

<charting:Chart>
  <charting:ColumnSeries ItemsSource="{Binding ScoreDistribution.ClassScores}"
                         IndependentValuePath="ClassName" DependentValuePath="Score"/>
</charting:Chart>

And the property on the viewmodel:

// NB: viewmodel derived from Josh Smith's BindableObject
public class ExamResultsViewModel : BindableObject
{
    // ...

    private ScoreDistributionByClass _scoreDistribution;
    public ScoreDistributionByClass ScoreDistribution
    {
        get
        {
            return _scoreDistribution;
        }
        set
        {
            if (_scoreDistribution == value)
            {
                return;
            }

            _scoreDistribution = value;

            RaisePropertyChanged(() => ScoreDistribution);
        }
    }

However, when I update the ScoreDistribution property (by setting it to a new ScoreDistribution object), the chart gets an additional series (based on the new ScoreDistribution) as well as keeping the original series (based on the previous ScoreDistribution).

To illustrate this, here are a couple of screenshots showing the chart before an update (with a single data point in ScoreDistribution.ClassScores) and after it (now with 3 data points in ScoreDistribution.ClassScores):

With a single data point

With 2 more data points added - note the original wide bar behind them

Now, I realise there are other ways I could be doing this (e.g. changing the contents of the original ScoreDistribution object rather than replacing it entirely), but I don't understand why it's going wrong in its current form. Can anyone help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

╰ゝ天使的微笑 2024-09-12 14:35:38

我也有同样的问题。当更改 DataPointSeries 的 ItemsSource 时,旧的 DataPoints 没有从图表中删除。

我在 WPF 工具包 (DataPointSeries.cs) 中的解决方法...

LoadDataPoints() 中使用 for 而不是 foreach 循环,因为我们更改了集合:

for (int i = oldItems.Count - 1; i >= 0; i--)

OnDataPointStateChanged() 中的 if 更改为:

if (dataPoint.State == DataPointState.Hidden || dataPoint.State == DataPointState.PendingRemoval)

这样 DataPoint 将被立即删除。

编辑
我还必须禁用 DataPoint 动画,如此处。

I had the same problem. When changing the ItemsSource of a DataPointSeries it happened that old DataPoints were not removed from the chart.

My workaround in the WPF Toolkit (DataPointSeries.cs)...

A for instead of a foreach loop in LoadDataPoints(), because we change the collection:

for (int i = oldItems.Count - 1; i >= 0; i--)

Change the if in OnDataPointStateChanged() to:

if (dataPoint.State == DataPointState.Hidden || dataPoint.State == DataPointState.PendingRemoval)

This way the DataPoint will be immediately removed.

Edit:
I also had to disable the DataPoint animation, described here.

等你爱我 2024-09-12 14:35:38

避免此问题的最简单方法是将系列 ItemSource 与 IsAsync 绑定为 True。

ItemsSource="{Binding DataItems, IsAsync=True}"

The most simple way to avoid this problem is to bind the serie ItemSource with IsAsync to True.

ItemsSource="{Binding DataItems, IsAsync=True}"
从﹋此江山别 2024-09-12 14:35:38

事实证明,问题是由图表中的更新频率触发的,而不是整个系列被替换的事实;将 databound 属性更改为 ObservableCollection 没有任何区别。

最后,我们更改了代码,以在底层数据的更改和 ViewModel 的绑定集合属性中反映的这些更改之间包含延迟。虽然它在一定程度上取决于运行应用程序的计算机的速度,但我们已确定最后一次基础数据更改和 ViewModel 属性更新之间有 0.5 秒的延迟。这可以防止图表更新频率超过每 0.5 秒,而且它似乎可以完成这项工作。

在某些时候,我实际上会浏览 WPFToolkit 代码并查看可以采取哪些措施来修复它,但目前,此解决方法值得注意。

Turns out the problem was triggered by the frequency of updates in the chart, not the fact that the entire series was being replaced; changing the databound property to an ObservableCollection made no difference.

In the end, we changed our code to include a delay between changes to the underlying data and those changes being reflected in the ViewModel's bound collection property. While it does depend to an extent on the speed of the machine on which the app is running, we've settled on a 0.5sec delay between the last underlying data change and the ViewModel property updating. This prevents the chart being updated more than every 0.5secs and it seems to do the job.

At some point, I'll actually go through the WPFToolkit code and see what I can do to fix it, but for now, this workaround's worth noting.

指尖上得阳光 2024-09-12 14:35:38

你正在做的事情应该有效。事实上,它并不表明 WPF Toolkit 有错误。

WPF Toolkit 在 DataPointSeries 上实现 OnItemsSourceChanged() 以检测替换 ItemsSource 并调用 Refresh() 的情况。 Refresh() 具有用于删除所有数据点(已经动画消失的数据点除外)的代码,然后创建一组全新的数据点。显然该代码有一个错误。我看了一两分钟,但没有发现什么问题。我首先升级到最新的 WPFToolkit 版本。如果这不能解决问题,您可以在更改 ItemsSource 时逐步执行 DataPointSeries.Refresh() 方法,以查看那里发生了什么以及为什么它不删除旧的 DataPoint 对象。

或者,正如您所观察到的,您可以通过仅替换集合内容而不是整个集合来解决该错误。

What you are doing ought to work. The fact that it doesn't indicates WPF Toolkit has a bug.

WPF Toolkit implements OnItemsSourceChanged() on DataPointSeries to detect the case where you replace ItemsSource and call Refresh(). Refresh() has code to remove all data points (except ones that are already animating away) and then create a whole new set of DataPoints. Obviously that code has a bug in it. I looked for a minute or two at it but didn't see what was wrong. I would start by upgrading to the latest WPFToolkit release. If that doesn't fix it, you might step through the DataPointSeries.Refresh() method when the ItemsSource is changed to see what is happening there and why it isn't removing the old DataPoint objects.

Or, as you observed, you could work around the bug by just replacing the collection content instead of the collection as a whole.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文