0

I'm having trouble binding data to the Modern UI Chart control.

Im not using it the common way where i create a XAML element and then bind to that, my goal is to create the element and render it in memory for then to fetch the image of the element.

My code below is for the creation and adding of content, the rendering of the image works fine.

    void generateGraphImg()
    {
        PieChart pc = new PieChart();
        ObservableCollection<TestClass>  Errors = new ObservableCollection<TestClass>();
        Errors.Add(new TestClass() { Category = "Globalization", Number = 75 });
        Errors.Add(new TestClass() { Category = "Features", Number = 2 });
        Errors.Add(new TestClass() { Category = "ContentTypes", Number = 12 });
        Errors.Add(new TestClass() { Category = "Correctness", Number = 83 });
        Errors.Add(new TestClass() { Category = "Best Practices", Number = 29 });

        ChartSeries Charts = new ChartSeries();
        Charts.SeriesTitle = "Errors";
        Charts.DisplayMember = "Category";
        Charts.ValueMember = "Number";
        Charts.ItemsSource = Errors;
        pc.Series.Add(Charts);

        pc.ChartTitle = "Minimal Pie Chart";
        pc.ChartSubTitle = "Chart with fixed width and height";

        makeImgFromControl(pc, @"C:\Modern UI IMG\img.bmp");
    }
    void makeImgFromControl(UIElement control, string saveTo)
    {
        Viewbox viewbox = new Viewbox();
        viewbox.Child = control; //control to render
        viewbox.Measure(new System.Windows.Size(200, 200));
        viewbox.Arrange(new Rect(0, 0, 200, 200));
        viewbox.UpdateLayout(); //On PiePiece DrawGeometry() happens here
        RenderTargetBitmap render = new RenderTargetBitmap(500,500, 150, 150, PixelFormats.Pbgra32);
        render.Render(viewbox);
        PngBitmapEncoder encoder = new PngBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(render));
        using (Stream s = File.Create(saveTo))
        {
            encoder.Save(s);
        }
    }

The binding of data does not render but, the title and sub-title renders fine any ideas to why?

Thomas Andreè Wang
  • 3,379
  • 6
  • 37
  • 53

2 Answers2

1

The solution was hiding in the LayoutUpdated, after a while hacking the code for the Modern UI Chart it dawned upon me. i need to wait before getting my img.

    void generateGraphImg()
    {
        PieChart pc = new PieChart();
        pc.LayoutUpdated += pc_LayoutUpdated;
        ObservableCollection<TestClass> Errors = new ObservableCollection<TestClass>();
        Errors.Add(new TestClass() { Category = "Globalization", Number = 75 });
        Errors.Add(new TestClass() { Category = "Features", Number = 2 });
        Errors.Add(new TestClass() { Category = "ContentTypes", Number = 12 });
        Errors.Add(new TestClass() { Category = "Correctness", Number = 83 });
        Errors.Add(new TestClass() { Category = "Best Practices", Number = 29 });

        ChartSeries Charts = new ChartSeries();
        Charts.SeriesTitle = "Errors";
        Charts.DisplayMember = "Category";
        Charts.ValueMember = "Number";
        Charts.ItemsSource = Errors;
        pc.Series.Add(Charts);

        pc.ChartTitle = "Minimal Pie Chart";
        pc.ChartSubTitle = "Chart with fixed width and height";

        makeImgFromControl(pc, @"C:\Modern UI IMG\img.bmp");
    }

    void pc_LayoutUpdated(object sender, EventArgs e)
    {
        RenderTargetBitmap render = new RenderTargetBitmap(500,500, 150, 150, PixelFormats.Pbgra32);
        render.Render(viewbox);
        PngBitmapEncoder encoder = new PngBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(render));
        using (Stream s = File.Create(@"C:\Modern UI IMG\img.bmp"))
        {
            encoder.Save(s);
        }
    }

    Viewbox viewbox;
    void makeImgFromControl(UIElement control, string saveTo)
    {
        viewbox = new Viewbox();
        viewbox.Child = control; //control to render
        viewbox.Measure(new System.Windows.Size(200, 200));
        viewbox.Arrange(new Rect(0, 0, 200, 200));
        viewbox.UpdateLayout();
    }
Thomas Andreè Wang
  • 3,379
  • 6
  • 37
  • 53
0

Try assigning the ItemSource after having added the ChartSeries. So change the order of:

Charts.ItemsSource = Errors;
pc.Series.Add(Charts);

to:

pc.Series.Add(Charts);
Charts.ItemsSource = Errors;

I tested and this seems to make a difference. Not exactly sure why, but it is possible the chart object only updates on receiving collection change notifications.


UPDATE: looking at the source code, it seems the pie chart is composed of PiePiece controls, which has in its constructor:

public PiePiece()
{
    ...
    Loaded += PiePiece_Loaded;
}

void PiePiece_Loaded(object sender, RoutedEventArgs e)
{
      DrawGeometry();
}

so it seems to only draw itself when actually Loaded.

Eren Ersönmez
  • 38,383
  • 7
  • 71
  • 92
  • No change on my end. the above is ALL my code on the subject, so you should be able to just copy that and run/test. – Thomas Andreè Wang Sep 17 '14 at 12:04
  • What is strange is that in both cases the image outputted is bigger than without the `pc.Series.Add(Charts);` so im thinking something is rendered but its just not visible somehow. – Thomas Andreè Wang Sep 17 '14 at 12:13
  • @ThomasAndreèLian yes, it is possible it is only rendered when actually Loaded. – Eren Ersönmez Sep 17 '14 at 12:17
  • when I display the chart on the UI, the order as I mentioned in the answer seems to make a difference. However, I'm trying your save to image method now, and it doesn't render the chart somehow. – Eren Ersönmez Sep 17 '14 at 12:19
  • 1
    @ThomasAndreèLian yes, it looks like what I suspected is the case. Updated the answer. I don't have an immediate workaround for you though. – Eren Ersönmez Sep 17 '14 at 12:26
  • Im poking around the code aswell, im having trouble finding where i can access the PiePiece I'm trying to make it possible to access the `DrawGeometry()` method. – Thomas Andreè Wang Sep 17 '14 at 13:18
  • debugged more and figgured out that the piepiece is redrawn on UpdateLayout(); – Thomas Andreè Wang Sep 22 '14 at 10:32