wpf 中的实时图表

Live chart in wpf

我必须为某些统计信息创建 wpf 应用程序。数据将来自数据库。 现在我尝试使用 LiveCharts 基本堆叠 CartesianChart。我想在主 window 中有 2 个不同的图表。所以我下载了一个例子,把它作为第一个图表,第二个我复制。

但是当我点击 运行 按钮生成图表时(图表中的数据是一些随机值,稍后它会来自 LIST)我只看到第一个图表第二个是空的。

此处xaml:

<ScrollViewer x:Name="ScrollViewerDay"
              VerticalScrollBarVisibility="Auto"
              HorizontalScrollBarVisibility="Hidden"
              Grid.Row="2"
              Grid.RowSpan="20"
              Grid.ColumnSpan="20">
    <StackPanel x:Name="StackDay"
                Grid.Column="0"
                Grid.Row="2"
                Grid.ColumnSpan="20"
                Grid.RowSpan="21"
                Margin="10,5,10,10">
        <Label x:Name="LabelDayTitle1"
               Content="Scrap Top10 (sorted by A2C number)"
               HorizontalAlignment="Center"
               HorizontalContentAlignment="Center"/>
        <lvc:CartesianChart x:Name="ChartDayA2C"
                            Series="{Binding SeriesCollectionDayA2C}"
                            LegendLocation="Bottom" MinHeight="280">
            <lvc:CartesianChart.AxisX>
                <lvc:Axis Title="Component scrap (Top10 A2C numbers) "
                          Labels="{Binding LabelsDayA2C}"
                          Separator="{x:Static lvc:DefaultAxes.CleanSeparator}" />
            </lvc:CartesianChart.AxisX>
            <lvc:CartesianChart.AxisY>
                <lvc:Axis Title="Usage"
                          LabelFormatter="{Binding FormatterDayA2C}">
                </lvc:Axis>
            </lvc:CartesianChart.AxisY>
        </lvc:CartesianChart>
        <Label x:Name="LabelDayTitle2"
               Content="Scrap Top10 (sorted by shape) "
               HorizontalContentAlignment="Center"
               HorizontalAlignment="Center"/>
        <lvc:CartesianChart x:Name="ChartDayShape"
                            Series="{Binding SeriesCollectionDayShape}"
                            LegendLocation="Bottom"
                            MinHeight="280">
            <lvc:CartesianChart.AxisX>
                <lvc:Axis Title="Component scrap (Top10 Shapes)"
                          Labels="{Binding LabelsDayShape}"
                          Separator="{x:Static lvc:DefaultAxes.CleanSeparator}" />
            </lvc:CartesianChart.AxisX>
            <lvc:CartesianChart.AxisY>
                <lvc:Axis Title="Usage"
                          LabelFormatter="{Binding FormatterDayShape}">
                </lvc:Axis>
            </lvc:CartesianChart.AxisY>
        </lvc:CartesianChart>
    </StackPanel>
</ScrollViewer>

这里是后面的代码:

private void BtDailyShow_Click(object sender, RoutedEventArgs e)
{
    SeriesCollectionDayA2C = new SeriesCollection
    {
        new StackedColumnSeries
        {
            Values = new ChartValues<double> {4, 5, 6, 8},
            StackMode = StackMode.Values, // this is not necessary, values is the default stack mode
            DataLabels = true
        },
        new StackedColumnSeries
        {
            Values = new ChartValues<double> {200, 5, 6, 7},
            StackMode = StackMode.Values,
            DataLabels = true
        }
    };

    //adding series updates and animates the chart
    SeriesCollectionDayA2C.Add(new StackedColumnSeries
    {
        Values = new ChartValues<double> { 6, 2, 7 },
        StackMode = StackMode.Values
    });

    //adding values also updates and animates
    SeriesCollectionDayA2C[2].Values.Add(4d);

    LabelsDayA2C = new[] { "Chrome", "Mozilla", "Opera", "IE" };
    FormatterDayA2C = value => value + " Mill";

    DataContext = this;

    SeriesCollectionDayShape = new SeriesCollection
    {
        new StackedColumnSeries
        {
            Values=new ChartValues<double> {20,40,60,80 },
            StackMode=StackMode.Values,
            DataLabels =true
        },
        new StackedColumnSeries
        {
            Values = new ChartValues<double> {100,200,300,400 },
            StackMode=StackMode.Values,
            DataLabels=true
        }
    };
    SeriesCollectionDayShape.Add(new StackedColumnSeries
    {
        Values = new ChartValues<double> { 30, 50, 60, 90 },
        StackMode = StackMode.Values
    });
    SeriesCollectionDayShape[2].Values.Add(4d);
    LabelsDayShape = new[] { "aaaa", "aass", "eeee", "laka" };
    FormmatterDayShape= value => value + " Mill";
    DataContext = this;
}

public SeriesCollection SeriesCollectionDayShape { get; set; }
public SeriesCollection SeriesCollectionDayA2C { get; set; }
public string[] LabelsDayA2C { get; set; }
public string[] LabelsDayShape { get; set; }
public Func<double, string> FormatterDayA2C { get; set; }
public Func<double,string> FormatterDayShape { get; set; }
public Func<object, object> FormmatterDayShape { get; set; }

谁能帮我看看错在哪里?

错误是行与

DataContext = this;

如果你删除它应该可以工作。在构造函数的末尾设置一次 DataContext

为什么?

wpf 中的绑定智能,它们能够监视属性的变化。为此,您必须为每种类型实施 INotifyPropertyChanged,并引发名称为 属性 的 PropertyChanged 事件,其值已发生变化。您可以通过上述所有操作使您的代码正常工作。

对于永远不会更改的属性,不需要通知,但这意味着您必须设置 DataContext 所有这些属性都设置了它们的值之后。

WPF 有很多优化,所以通常在 属性 setter 里面有一个 check if value is a new,这会导致很多问题,包括你的情况。另一种解决问题的方法是以 hacky 方式执行 refresh 值:

DataContext = this; // first time
...

DataContext = null;
DataContext = this; // refresh the value