Search code examples
c#wpflivecharts

WPF LiveChart rendering from usercontrol


I´m trying to render a Cartesian Chart from a usercontrol. The textblock just renders fine but unfortunately the chart isn`t shown. I´ve no clue how to fix this. Could anybody give me a hint?

This is the function for rendering the graph and save it as a pngfile.

public void ConvertGraph(Object dataContext)
        {
            UserControl ucGraph = new Graph
            {
                DataContext = dataContext
            };
            ucGraph.Measure(new Size(400, 400));
            ucGraph.Arrange(new Rect(new Size(400, 400)));
            ucGraph.UpdateLayout();

            RenderTargetBitmap bmp = new RenderTargetBitmap(400, 400, 96, 96, PixelFormats.Pbgra32);
            
            bmp.Render(ucGraph);

            var encoder = new PngBitmapEncoder();

            encoder.Frames.Add(BitmapFrame.Create(bmp));

            using (Stream stm = File.Create(@"c:\Temp\test.png"))
                encoder.Save(stm);

        }

This is the UserControl.

<UserControl x:Class="LogAnalyzerWpf.Views.PrintViews.Graph"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:LogAnalyzerWpf.Views.PrintViews"
             xmlns:vm="clr-namespace:LogAnalyzerWpf.ViewModels"
             xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800"
             Background="White">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="20"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0" Text="{Binding HighLevelAlarm}"></TextBlock>
        
        <lvc:CartesianChart DisableAnimations="True" Grid.Column="0" Grid.Row="1" LegendLocation="Bottom" Series="{Binding seriesCollection}">
            <lvc:CartesianChart.AxisX>
                <lvc:Axis Title="Date" Labels="{Binding DateTimeValues}"></lvc:Axis>
            </lvc:CartesianChart.AxisX>
            <lvc:CartesianChart.AxisY>
                <lvc:Axis Title="Temperature (°C)"/>
                <lvc:Axis Title="Level (mm)" Position="RightTop" />
            </lvc:CartesianChart.AxisY>
        </lvc:CartesianChart>
    </Grid>
</UserControl>

Solution

  • I got it to work by making a couple of changes.

    1. In your ConvertGraph method, change UserControl ucGraph = new Graph to be Graph ucGraph = new Graph
    2. In your xaml, give your lvc:CartesianChart a name like x:Name="chart"
    3. In your ConvertGraph method, right before you call ucGraph.UpdateLayout(), also call ucGraph.chart.Update(true,true); which will force it to redraw itself

    Instructions outlined here: https://github.com/Live-Charts/Live-Charts/blob/develop/Examples/Wpf/CartesianChart/Chart%20to%20Image/ChartToImageSample.xaml.cs

    As a side note, I'd also recommend setting DisableAnimations on the chart to be true, so that it doesn't mess with your renders while saving (might be important if the chart is complicated).