WPF Toolkit Chart ScatterSeries не отображает точки данных

У меня есть две диаграммы в моем приложении, я использую System.Windows.Controls.DataVisualization.Toolkit.

Одна диаграмма отображает элементы LineSeries, где каждая новая точка данных добавляется отдельно. Эта диаграмма использует

    ObservableCollection<KeyValuePair<int, double>>

модель как ItemsSource. Это работает так же, как и ожидалось. Показывает линии и маркеры.

На другой диаграмме показан график XYPlot с произвольным количеством точек данных, протестированных с 15, 50, 1500 и т. Д. Он использует ScatterSeries для отображения точек данных. Он использует

    ObservableCollection<KeyValuePair<double, double>>

модель как ItemsSource.

(Изменить: я начинаю подозревать, что, возможно, моя проблема заключается в том факте, что мои независимые значения X являются значениями с плавающей запятой в случае второго графика, который может не быть поддерживаемым вариантом использования для ScatterSeries - или вообще, для этого типа контроля диаграммы?)

Вторая диаграмма работает (хорошо, более или менее), если я изменяю ScatterSeries на LineSeries, но даже в этом случае отображаются только линии, а не маркеры точек. Почему-то я не могу сделать второй график для отображения маркеров точек.В случае второго графика крайне важно, чтобы я не добавлял баллы по отдельности, а всегда заменял весь ряд новым. Я попытался реализовать класс ObservableCollectionEx, который реализует функцию ReplaceAll и отправляет либо событие NotifyCollectionChangedAction.Replace, либо NotifyCollectionChangedAction.Reset вместе с событием NotifyCollectionChangedAction.Add, но безуспешно. Я пытался обновлять ItemsSource новой коллекцией каждый раз, когда обновляются данные, но все же не повезло.

Все мои приведенные выше попытки, кажется, работают нормально, если я выбираю LineSeries (без отображения маркеров), но когда я хочу видеть только маркеры, используя ScatterSeries, они вообще не отображаются. Я могу видеть диапазон изменения осей, как если бы он правильно следовал за диапазоном данных, но ничего не нарисовано.

Где я могу пойти не так? Являются ли ScatterSeries или вообще маркеры на графике другим способом?

Вот мой график, который работает:

    <DVC:Chart Name="errors" Grid.Row="2" Width="auto" Height="auto">
        <DVC:Chart.Axes>
            <DVC:LinearAxis Orientation="X" FontSize="10" Title="Mean Squared Error"/>
            <DVC:LinearAxis Orientation="Y" FontSize="10" ShowGridLines="True"/>
        </DVC:Chart.Axes>
        <DVC:Chart.LegendStyle>
            <Style TargetType="{x:Type DV:Legend}">
                <Setter Property="Width" Value="0" />
            </Style>
        </DVC:Chart.LegendStyle>
        <DVC:LineSeries DataContext="{Binding ErrorList}" ItemsSource="{Binding}" IndependentValuePath="Key" DependentValuePath="Value" />
    </DVC:Chart>

А вот мой график, который отображает только линии, но не маркеры:

    <DVC:Chart Grid.Row="4" x:Name="dataFit" Width="auto" Height="auto">
        <DVC:Chart.Axes>
            <DVC:LinearAxis Orientation="X" FontSize="10" Title="Regression"/>
            <DVC:LinearAxis Orientation="Y" FontSize="10" ShowGridLines="True"/>
        </DVC:Chart.Axes>
        <DVC:Chart.Series>
            <DVC:ScatterSeries Name="scatterPlot" ItemsSource="{Binding DataFitList}" IndependentValueBinding="{Binding Path=Key}" DependentValueBinding="{Binding Path=Value}">
                <DVC:ScatterSeries.DataPointStyle>
                    <Style TargetType="{x:Type DVC:ScatterDataPoint}">
                        <Setter Property="Visibility" Value="Visible"/>
                        <Setter Property="Height" Value="10"/>
                        <Setter Property="Width" Value="10"/>
                    </Style>
                </DVC:ScatterSeries.DataPointStyle>
            </DVC:ScatterSeries>
        </DVC:Chart.Series>
        <DVC:Chart.LegendStyle>
            <Style TargetType="{x:Type DV:Legend}">
                <Setter Property="Width" Value="0" />
            </Style>
        </DVC:Chart.LegendStyle>
    </DVC:Chart>

Вы можете видеть, что я пытался вручную изменить стиль маркеров, это не имеет никакого эффекта вообще. Когда я изменил его на LineSeries, я смог изменить свойства линий таким же образом.

Я пробовал несколько способов обновить данные. Некоторые фрагменты моих испытаний:

Сначала используйте только привязку, пытаясь заменить все данные в ObservableCollection:

public class ScatterPlotCollection : ObservableCollectionEx<KeyValuePair<double, double>>
{
    public ScatterPlotCollection() : base() { }
}

public class ObservableCollectionEx<T> : ObservableCollection<T>
{
    public void ReplaceAt(T newElement, int index)
    {
        CheckReentrancy();
        if (index < 0 || index >= Items.Count())
            return;
        T oldElement = Items[index];
        Items[index] = newElement;
        this.OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, newElement, oldElement, index));
    }

    public void ReplaceAll(IEnumerable<T> dataToAdd)
    {
        CheckReentrancy();
        int startingIndex = 0;

        List<T> oldItems = Items.ToList();
        Items.Clear();
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, oldItems, startingIndex));
        ((List<T>)Items).AddRange(dataToAdd);

        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, dataToAdd, startingIndex));
    }

    public void AddRange(IEnumerable<T> dataToAdd)
    {
        CheckReentrancy();
        int startingIndex = this.Count;
        foreach (var data in dataToAdd)
        {
            this.Items.Add(data);
        }

        this.OnPropertyChanged(new PropertyChangedEventArgs("Count"));
        this.OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));

        var changedItems = new List<T>(dataToAdd);
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, changedItems, startingIndex));
    }
}

Затем я попробовал метод грубой силы, просто назначая ScatterSeries новый ItemsSource каждый раз, когда я хочу перерисовать его:

((ScatterSeries)dataFit.Series[0]).ItemsSource = tempDataFitList.ToArray();
((ScatterSeries)dataFit.Series[0]).Refresh();

Обе попытки (связывание и изменение ItemsSource), кажется, работают нормально, когда я отображаю LineSeries (без маркеров), ни одна из них, кажется, не работает, когда я отображаю ScatterSeries.

Редактировать: Это пришло мне в голову после сортировки моих мыслей по этому вопросу: возможно ли, что, хотя я использую два отдельных элемента управления Chart в одном и том же окне, они каким-то образом совместно используют общий буфер данных или общий контейнер для данных точки? А может быть, первый график влияет на то, как работает мой второй график?

Что мне не хватает?

(Вот весь проект, нетрудно добраться до точки, где отображаются графики, только для просмотра, если я пропустил упоминание чего-то важного в этом вопросе:

Целое решение: https://github.com/bulyaki/DeepTrainer

Проект WPF: https://github.com/bulyaki/DeepTrainer/tree/master/NNTrainerTesterWPF)

0 ответов

Другие вопросы по тегам