Click here to Skip to main content
13,141,576 members (54,673 online)
Click here to Skip to main content
Add your own
alternative version


21 bookmarked
Posted 4 Feb 2014

WPF Bar Chart as simple as possible

, 27 May 2014
Rate this:
Please Sign up or sign in to vote.
Creating a bar chart with most of needed features.


Most of User controls in WPF are heavy to load, specially when we use them inside another control(e.g. DataGrid). If we use a DataGrid, Chart or another control inside the rows details in DataGrid, it makes our form's loading too slow. Because of that,I decided to create a light weight BarChart control to decrease this problem.

In this control we can bind items and legends to it's ItemsSource property. There are 3 properties to introducing horizontal, vertical and legends properties in Item source to chart, : HorizontalPropertyName, VerticalPropertyName and LegendPropertyName.

In additional of this, we can change some appearance parameters such as changing visibility of Values labels and Legends list, and manipulating legends header and color.

Using the code

In control's class, Draw() method creates our view by using our ItemsSource or Items properties. In some events we call this method to refresh our view. This method creates a Border control per each information, then locates that on a canvas by calculating its location. For calculating our drawing area and borders, we use count of legends and horizontal values. Borders width dynamically changes by control width and count of legends.

Our second main method is GetLegends(). By using this method we can fetch all of legends by there property name declared in LegendPropertyName property.

private void GetLegends()
    if (Legends == null)
        Legends = new ObservableCollection<Legend>();
    if (Items == null)
    Random rand = new Random(DateTime.Now.Millisecond);
    foreach (var item in Items)
        var LegValue = item.GetType().GetProperty(LegendPropertyName).GetValue(item, null);
        var leg = from Legend lc in Legends where lc.LegendType.Equals(LegValue) select lc;
        if (leg.Count() == 0)
             Legend legend = new Legend();
             legend.LegendType = LegValue;
             Color c = Color.FromRgb(Convert.ToByte(rand.Next(256)), Convert.ToByte(rand.Next(256)), Convert.ToByte(rand.Next(256)));
             legend.Color = new SolidColorBrush(c);
             legend.IsVisibleChanged += (s, e) =>
        leg.First().IsVisibleChanged += (s, e) =>

For declaring legends and changing there property, I defined a class with name Legend that inherits from DependencyObject and INotifyPropertyChanged. We have some properties(LegendType, DisplayName, Color and IsVisible) and one event(IsVisibleChanged) in this class.

public class Legend : DependencyObject, INotifyPropertyChanged
        #region Constructors
        public Legend()
        #endregion Constructors
        #region Properties
        private object _legend = null;
        public object LegendType
            get { return _legend; }
                _legend = value;
        private string _displayName = String.Empty;
        public string DisplayName
                if (String.IsNullOrEmpty(_displayName))
                    if (LegendType == null)
                        return String.Empty;
                        return LegendType.ToString();
                    return _displayName;
                _displayName = value;
        private Brush _color = null;
        public Brush Color
            get { return _color; }
                _color = value;
        private bool _isVisible = true;
        public bool IsVisible
            get { return _isVisible; }
                if (_isVisible != value)
                    _isVisible = value;
                    if (IsVisibleChanged != null)
                        IsVisibleChanged(this, new RoutedEventArgs());
        #endregion Properties
        #region Events
        public event RoutedEventHandler IsVisibleChanged;
        #endregion Events
        #region Methods
        public event PropertyChangedEventHandler PropertyChanged;
        private void Notify(string property)
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        #endregion Methods

For using this control we can declare a class or structure for passing main properties to it and use them to draw bars. For example, I declared a simple class to do this.

public class MyData
       public MyData()

       public int Year { get; set; }

       public double Value { get; set; }

       public WorkTypes WorkType { get; set; }

And an Enum to indicate my legends.

public enum WorkTypes

By using a List, ArrayList, ObservableCollection or other classes inherited from IEnumerable, we can create an array of our class and pass that to controls Items property or bind that to ItemsSource property.

<controls:BarChart x:Name="BarChart1"
                   ItemsSource="{Binding Path=Data,
                                 RelativeSource={RelativeSource AncestorType=Window}}">

In above code, I passed "WorkType" to LegendPropertyName, "Value" to VerticalPropertyName and Year to HorizontalPropertyName to use this names for accessing value of this properties in my class. For presenting my information in chart, I binded Data property in my class to ItemsSource property of control.

For customizing legends, User can change their attributes and properties. Some thing like this :

     <controls:Legend DisplayName="Buy" LegendType="{x:Static my:WorkTypes.Buy}">
               <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
                     <GradientStop Color="#FF5C8EFF" Offset="0" />
                     <GradientStop Color="#FFC2C2FC" Offset="1" />
     <controls:Legend DisplayName="Sell" LegendType="{x:Static my:WorkTypes.Sell}">
               <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
                    <GradientStop Color="#FF63B700" Offset="0" />
                    <GradientStop Color="#FFBDEB94" Offset="1" />
     <controls:Legend DisplayName="Receipt" LegendType="{x:Static my:WorkTypes.Receipt}">
               <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
                     <GradientStop Color="#FFA9B700" Offset="0" />
                     <GradientStop Color="#FFEBEB94" Offset="1" />
     <controls:Legend DisplayName="Draft" LegendType="{x:Static my:WorkTypes.Draft}">
               <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
                      <GradientStop Color="#FFB700B7" Offset="0" />
                      <GradientStop Color="#FFD794EB" Offset="1" />

Points of Interest

In this control, I used dynamic property names for my first time. With dynamic property names, we can improve control's flexibility and use controls in every forms and projects without needing any [large] changes.


I hope this code and this user control help you to creating new controls.

I apologies for my poor description because of my weak English knowledge.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Software Developer (Senior) Keyhan Iranian
Iran (Islamic Republic of) Iran (Islamic Republic of)
I'm addict of developing softwares and designing solutions for projects.
My favorite work in programming is designing Components and user controls.

You may also be interested in...


Comments and Discussions

Bugnice post but there is a bug...... Pin
Member 1257355723-Sep-16 23:51
memberMember 1257355723-Sep-16 23:51 
GeneralRe: nice post but there is a bug...... Pin
S.A.Esmaeily9-Oct-16 0:39
professionalS.A.Esmaeily9-Oct-16 0:39 
QuestionHow to make line chart Pin
Radhakrishnan V16-Jun-15 2:19
memberRadhakrishnan V16-Jun-15 2:19 
AnswerRe: How to make line chart Pin
S.A.Esmaeily23-Jun-15 23:55
professionalS.A.Esmaeily23-Jun-15 23:55 
GeneralRe: How to make line chart Pin
Radhakrishnan V25-Jun-15 23:36
memberRadhakrishnan V25-Jun-15 23:36 
AnswerRe: How to make line chart Pin
S.A.Esmaeily12-Jul-15 3:38
professionalS.A.Esmaeily12-Jul-15 3:38 
QuestionNice post Esmaeily Pin
Radhakrishnan V16-Jun-15 2:16
memberRadhakrishnan V16-Jun-15 2:16 
QuestionRE:WPF Bar Chart as simple as possible Pin
Jacob Lee11-Nov-14 20:17
memberJacob Lee11-Nov-14 20:17 
AnswerRe: WPF Bar Chart as simple as possible Pin
S.A.Esmaeily13-Nov-14 0:41
professionalS.A.Esmaeily13-Nov-14 0:41 
GeneralRe: WPF Bar Chart as simple as possible Pin
Radhakrishnan V25-Jun-15 23:40
memberRadhakrishnan V25-Jun-15 23:40 
QuestionWeird behaviour Pin
fireblade200927-Oct-14 9:08
memberfireblade200927-Oct-14 9:08 
AnswerRe: Weird behaviour Pin
S.A.Esmaeily27-Oct-14 18:58
professionalS.A.Esmaeily27-Oct-14 18:58 
QuestionIt looses the look and feel when scaled Pin
Sacha Barber4-Feb-14 2:19
mvpSacha Barber4-Feb-14 2:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.170915.1 | Last Updated 28 May 2014
Article Copyright 2014 by S.A.Esmaeily
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid