1

I have to create wpf application for some statistic. Data will come from DB. Now I try to use LiveCharts basic stacked CartesianChart. I would like to have 2 different charts in main window. So I download a example put it as first chart and for second I make copy.

But when I click on run button to generate charts (data in chart is some random values, later it will come from LIST) I see just first chart second is empty.

Here 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>

and here code behind:

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; }

Can somebody help me where is a mistake?

Sinatr
  • 20,892
  • 15
  • 90
  • 319
LukasVanek
  • 139
  • 1
  • 2
  • 10
  • Which witch is which? Which chart is first/second? It would be nice if you add comment to xaml (and please spend few seconds to format xaml before hitting `Post` button, you can see how bad it looks currently in preview). – Sinatr Aug 01 '18 at 10:21
  • In both ( cs and xaml ) is first first one from top - SeriesCollectionDayA2C and x:Name="ChartDayA2C" – LukasVanek Aug 01 '18 at 19:04
  • @Sinatr please help me how to format xaml better??? I'm new in this communitzyand want to learn from somebody with experience thx – LukasVanek Aug 01 '18 at 19:07

1 Answers1

3

The mistake is first line with

DataContext = this;

It should work if you remove it. Set DataContext once at the end of constructor.

Why?

Bindings in wpf are smart, they are able to monitor for changes of properties. For this you have to implement INotifyPropertyChanged for each type, and rise PropertyChanged event with name of property what has its value changed. You could make your code working by doing all said.

For properties which are never changed notifications is not needed, but that means what you have to set DataContext after all such properties have their value set.

WPF has many optimizations, so typically inside property setter there is a check if value is a new, which cause many problems, including your case. Another possibility to fix your issue is to perform refresh of value in a hacky way:

DataContext = this; // first time
...

DataContext = null;
DataContext = this; // refresh the value
Sinatr
  • 20,892
  • 15
  • 90
  • 319