Posted by: Zeeshan Amjad | November 27, 2011

Creating High Low Graph


High low graph is very common in financial domain. In this graph we display only the low and high value of the stock. We already saw the example of creating the bar graph here and here. Now we are going to modify the program to display the high and low value of individual stock. Let’s first create the data structure to store the data. Here is our data structure.

Code Snippet
public class DataPoint
{
    public string Name
    { get; set; }

    public double Counter
    { get; set; }

    public double High
    { get; set; }

    public double Low
    { get; set; }
}

 

Notice there is no Color property here. We created one converter to convert the counter into color. Here is our converter.

Code Snippet
public class ColorConverter : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        int converter = Int16.Parse(value.ToString());
        converter %= 10;
        
        switch (converter)
        {
            case 0:
                return new SolidColorBrush(Colors.Black);

            case 1:
                return new SolidColorBrush(Colors.Red);

            case 2:
                return new SolidColorBrush(Colors.Blue);

            case 3:
                return new SolidColorBrush(Colors.Green);

            case 4:
                return new SolidColorBrush(Colors.Yellow);

            case 5:
                return new SolidColorBrush(Colors.Violet);

            case 6:
                return new SolidColorBrush(Colors.Wheat);

            case 7:
                return new SolidColorBrush(Colors.Indigo);

            case 8:
                return new SolidColorBrush(Colors.Cyan);

            case 9:
                return new SolidColorBrush(Colors.Navy);
        }

        return Colors.Black;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

 

The important thing about high low graph is we are going to create a bar with only low value to high value. We create one multi value converter for this purpose. The whole purpose of the multi value converter is to calculate the range to display the rectangle in appropriate height. Here is our multi value converter.

Code Snippet
public class RangeConverter : IMultiValueConverter
{

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double high = (double)values[0];
        double low = (double)values[1];

        return high – low;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

 

We have to create one more important converter and that is label converter. We are going to display all the label at fixed height, in this example 50. But where to start displaying the rectangle, which internally uses the stack panel in item panel data template. We uses one simple technique to increase the width of text block by the low value of the stock, so the rectangle will start displaying from the low value of the stock. Here is our label converter.

Code Snippet
public class LabelConverter : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double low = (double)value;

        return low + 50;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

 

Here is our data template to display the rectangle and text block by using appropriate converters.

Code Snippet
<DataTemplate>
    <StackPanel>
        <Rectangle Width="15" Fill="{Binding Counter, Converter={StaticResource colorConverter}}">
            <Rectangle.Height>
                <MultiBinding Converter="{StaticResource rangeConverter}">
                    <Binding Path="High"/>
                    <Binding Path="Low"/>
                </MultiBinding>
            </Rectangle.Height>
        </Rectangle>
        <TextBlock Margin="5" Text="{Binding Name}"
                    Width="{Binding Low, Converter={StaticResource labelConverter}}">
            <TextBlock.LayoutTransform>
                <RotateTransform Angle="270"/>
            </TextBlock.LayoutTransform>
        </TextBlock>
    </StackPanel>
</DataTemplate>

 

Rest of the program is very similar to the previous one. Here is complete XAML of the program.

Code Snippet
<Window x:Class="WpfHighLowGraph.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        xmlns:local="clr-namespace:WpfHighLowGraph"
        Title="High Low Graph" Height="300" Width="300">
    <Window.Resources>
        <local:CounterConverter x:Key="objConverter"/>
        <local:RangeConverter x:Key="rangeConverter"/>
        <local:LabelConverter x:Key="labelConverter"/>
        <local:ColorConverter x:Key="colorConverter"/>
        <Style x:Key="myStyle" TargetType="ListBoxItem">
            <Setter Property="Canvas.Left"
                    Value="{Binding Path=Counter, Converter={StaticResource objConverter}}"/>
            <Setter Property="Canvas.Bottom" Value="50"/>
        </Style>
    </Window.Resources>
    <Grid>
        <ListBox Margin="5" ItemsSource="{Binding}" ItemContainerStyle="{StaticResource myStyle}">
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas/>
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <Rectangle Width="15" Fill="{Binding Counter, Converter={StaticResource colorConverter}}">
                            <Rectangle.Height>
                                <MultiBinding Converter="{StaticResource rangeConverter}">
                                    <Binding Path="High"/>
                                    <Binding Path="Low"/>
                                </MultiBinding>
                            </Rectangle.Height>
                        </Rectangle>
                        <TextBlock Margin="5" Text="{Binding Name}"
                                    Width="{Binding Low, Converter={StaticResource labelConverter}}">
                            <TextBlock.LayoutTransform>
                                <RotateTransform Angle="270"/>
                            </TextBlock.LayoutTransform>
                        </TextBlock>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

 

And here is complete C# code of the program. Of course all the data in this program is not real.

Code Snippet
using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;

namespace WpfHighLowGraph
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        ObservableCollection<DataPoint> data = new ObservableCollection<DataPoint>();

        public MainWindow()
        {
            InitializeComponent();

            data.Add(new DataPoint() { Name = "Microsoft", Counter = 1, High = 50, Low = 15 });
            data.Add(new DataPoint() { Name = "Intel", Counter = 2, High = 60, Low = 35 });
            data.Add(new DataPoint() { Name = "Google", Counter = 3, High = 40, Low = 10 });
            data.Add(new DataPoint() { Name = "Apple", Counter = 4, High = 120, Low = 90 });
            data.Add(new DataPoint() { Name = "Wallmart", Counter = 5, High = 65, Low = 45 });
            data.Add(new DataPoint() { Name = "Boeing", Counter = 6, High = 35, Low = 10 });
            data.Add(new DataPoint() { Name = "Adobe", Counter = 7, High = 90, Low = 75 });
            data.Add(new DataPoint() { Name = "CVS", Counter = 8, High = 50, Low = 35 });
            data.Add(new DataPoint() { Name = "Starbucks", Counter = 9, High = 130, Low = 105 });
            data.Add(new DataPoint() { Name = "Amazon", Counter = 10, High = 75, Low = 55 });

            DataContext = data;
        }
    }

    public class DataPoint
    {
        public string Name
        { get; set; }

        public double Counter
        { get; set; }

        public double High
        { get; set; }

        public double Low
        { get; set; }
    }

    public class ColorConverter : IValueConverter
    {

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            int converter = Int16.Parse(value.ToString());
            converter %= 10;
            
            switch (converter)
            {
                case 0:
                    return new SolidColorBrush(Colors.Black);

                case 1:
                    return new SolidColorBrush(Colors.Red);

                case 2:
                    return new SolidColorBrush(Colors.Blue);

                case 3:
                    return new SolidColorBrush(Colors.Green);

                case 4:
                    return new SolidColorBrush(Colors.Yellow);

                case 5:
                    return new SolidColorBrush(Colors.Violet);

                case 6:
                    return new SolidColorBrush(Colors.Wheat);

                case 7:
                    return new SolidColorBrush(Colors.Indigo);

                case 8:
                    return new SolidColorBrush(Colors.Cyan);

                case 9:
                    return new SolidColorBrush(Colors.Navy);
            }

            return Colors.Black;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class CounterConverter : IValueConverter
    {

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            double counter = (double)value;

            return counter * 20;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class RangeConverter : IMultiValueConverter
    {

        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            double high = (double)values[0];
            double low = (double)values[1];

            return high – low;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class LabelConverter : IValueConverter
    {

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            double low = (double)value;

            return low + 50;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

 

Here is an output of the program.

HighLowGraph

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: