klaus
klaus

Reputation: 159

PieChart Does Not Show Up

I need to display a PieChart, I'm currently using Modern UI (Metro) Charts. I did copy the code in the documentation and the problem is that i'm always having the border and the title in the screen but no chart.

XAML

<UserControl x:Class="Projet.Recources0.Statistique.Ad_Aj"
         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:mui="http://firstfloorsoftware.com/ModernUI"
         xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
         xmlns:chart="clr-namespace:De.TorstenMandelkow.MetroChart;assembly=De.TorstenMandelkow.MetroChart"
         mc:Ignorable="d" d:DesignWidth="1000" Height="670">

<UserControl.Resources>
    <Style x:Key="MinimalChartStyle" TargetType="{x:Type chart:ChartBase}">
        <Setter Property="Width" Value="500"/>
        <Setter Property="Height" Value="500"/>            
    </Style>
</UserControl.Resources>
<Grid >
    <chart:PieChart
    Style="{StaticResource MinimalChartStyle}"
    ChartTitle="Minimal Pie Chart"
    ChartSubTitle="Chart with fixed width and height"
    SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}" >
        <chart:PieChart.Series>
            <chart:ChartSeries
            SeriesTitle="Errors"
            DisplayMember="Category"
            ValueMember="Number"
            ItemsSource="{Binding Path=Errors}" />
        </chart:PieChart.Series>
    </chart:PieChart>
</Grid>

CS

using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Projet.Recources0.Statistique
{
    /// <summary>
    /// Interaction logic for Ad_Aj.xaml
    /// </summary>

    public partial class Ad_Aj : UserControl
    {
        public ObservableCollection<TestClass> Errors { get; private set; }

        public Ad_Aj()
        {
            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 });
        }

        private object selectedItem = null;
        public object SelectedItem
        {
            get
            {
                return selectedItem;
            }
            set
            {
                // selected item has changed
                selectedItem = value;                
            }
        }
    }

    // class which represent a data point in the chart
    public class TestClass
    {
        public string Category { get; set; }

        public int Number { get; set; }
    }
}

Pie Chart

Upvotes: 5

Views: 953

Answers (3)

jsanalytics
jsanalytics

Reputation: 13188

Create a ViewModel to hold data for your chart and assign it to your DataContext as shown below:

XAML:

<Window x:Class="WpfApplication222.Window2"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:chart="clr-namespace:De.TorstenMandelkow.MetroChart;assembly=De.TorstenMandelkow.MetroChart" 
    xmlns:local="clr-namespace:WpfApplication222"
    mc:Ignorable="d"
    Title="Window2" Height="350" Width="525">

<Window.DataContext>
    <local:PieChartViewModel/>
</Window.DataContext>

<Grid>
    <chart:PieChart
        ChartTitle="Minimal Pie Chart"
        ChartSubTitle="Chart with fixed width and height"
        SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}" >
        <chart:PieChart.Series>
            <chart:ChartSeries
                SeriesTitle="Errors"
                DisplayMember="Category"
                ValueMember="Number"
                ItemsSource="{Binding Path=Errors}" />
        </chart:PieChart.Series>
    </chart:PieChart>
</Grid>

ViewModel:

public class PieChartViewModel
{
    public ObservableCollection<TestClass> Errors { get; private set; }

    public PieChartViewModel()
    {
        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 });
    }
}

enter image description here

EDIT: Rather than having your ViewModel created in XAML as before, you can also do it dynamically as follows:

XAML:

Window x:Class="WpfApplication222.Window2"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:chart="clr-namespace:De.TorstenMandelkow.MetroChart;assembly=De.TorstenMandelkow.MetroChart" 
    xmlns:local="clr-namespace:WpfApplication222"
    mc:Ignorable="d"
    Title="Window2" Height="350" Width="525" Loaded="Window_Loaded">

<Grid>
    <chart:PieChart
        ChartTitle="Minimal Pie Chart"
        ChartSubTitle="Chart with fixed width and height"
        SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}" >
        <chart:PieChart.Series>
            <chart:ChartSeries
                SeriesTitle="Errors"
                DisplayMember="Category"
                ValueMember="Number"
                ItemsSource="{Binding Path=Errors}" />
        </chart:PieChart.Series>
    </chart:PieChart>
</Grid>

CS:

public partial class Window2 : Window
{
    PieChartViewModel viewModel;

    public Window2()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        viewModel = new PieChartViewModel();

        viewModel.Errors.Add(new TestClass() { Category = "Globalization", Number = 75 });
        viewModel.Errors.Add(new TestClass() { Category = "Features", Number = 2 });
        viewModel.Errors.Add(new TestClass() { Category = "ContentTypes", Number = 12 });
        viewModel.Errors.Add(new TestClass() { Category = "Correctness", Number = 83 });
        viewModel.Errors.Add(new TestClass() { Category = "Best Practices", Number = 29 });

        DataContext = viewModel;
    }
}

ViewModel:

public class PieChartViewModel
{
    public ObservableCollection<TestClass> Errors { get; private set; }

    public PieChartViewModel()
    {
        Errors = new ObservableCollection<TestClass>();
    }
}

Upvotes: 1

Cameron
Cameron

Reputation: 2594

So you're off to the right track! You're only missing one line of code!

public partial class Ad_Aj : UserControl
{
    public ObservableCollection<TestClass> Errors { get; private set; }

    public Ad_Aj()
    {
        /*
         * ----------------------------
         * This is line you're missing.
         * ----------------------------
         */
        DataContext = this;
        /*
         * ----------------------------
         */
        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 });
    }
}

This is MVVM, but it's not true MVVM. True MVVM has a separate ViewModel class. What you're are doing here is using the Code-Behind of your View as your ViewModel. It works, and no one will fight you on that. However, if you're trying to do true MVVM, then you'll need to separate out your classes.

jstreet has a great answer/example of how to set your DataContext (aka the "binding") to the ViewModel in XAML.

<Window.DataContext>
    <local:PieChartViewModel />
</Window.DataContext>

However, take note that he's using a separate ViewModel class. The code you provided in your question does not do this, so I'm not sure how to do it the same way. Also, it's worth mentioning that if your ViewModel class uses constructor dependency injection or has parameters, that you're going to have to use some magic to get this to work. If that's the case, it's easier to just set it in the constructor.

Upvotes: 1

Chiune Sugihara
Chiune Sugihara

Reputation: 1229

I am not an expert with the control but I am guessing that your ItemsSource binding is failing. The Errors collection is on the user control as a property and your binding on the ItemsSource is by default going to go off of the DataContext which I am thinking is null in your case. To get the the control directly through a binding you would likely get it to work with the RelativeSource markup extension by doing something like (assuming that you map "local" to the namespace where Ad_Aj is located):

ItemsSource = "{Binding RelativeSource={RelativeSource AncestorType=local:Ad_Aj, Mode=FindAncestor}, Path=Errors}"

I think though that you would want to put your Errors information in a view model and then set that to the data context and use the bindings as you have them since the Errors information is really data and separate from the UI.

Upvotes: 0

Related Questions