Posted by: Zeeshan Amjad | August 28, 2012

First experience with Mindscape


I came across one commercial WPF library Mindscape. You can get the detail about it from here. The first thing I tried in the library is their graph / chart. Like other commercial libraries, they have extensive coverage of graph and I wanted to test couple of graph. I already made a loan amortization program here so it would be a perfect choice for me to make a graph for that application. I changed the user interface of the program little bit and introduced different tabs to display different information. I found it quite easy to use and able to make my first graph within 5 minutes with the help of their sample. But there is one place where I found the documentation is not clear enough and I have to spend some time to figure it out.

First lets take a look at our application. First we create a simple class to store different attributes of one single payment such as payment no, amount, principle amount, interest amount and remaining balance. Here is our class.

Code Snippet
public class PaymentInfo
{
    public int PaymentNo
    { get; set; }

    public double Payment
    { get; set; }

    public double Principle
    { get; set; }

    public double Interest
    { get; set; }

    public double Balance
    { get; set; }
}

 

We have multiple payment so we need one class to store all the payment information. We create one class for information about all the amortization data. Here is our class.

Code Snippet
public class AmortizationData : INotifyPropertyChanged
{
    private double _loanAmount;
    private double _interestRate;
    private double _payment;
    private double _totalInterest;
    private int _duration;
    private ObservableCollection<PaymentInfo> _payments;

    public AmortizationData()
    {
        _payments = new ObservableCollection<PaymentInfo>();
    }

    public double LoanAmount
    {
        get
        {
            return _loanAmount;
        }
        set
        {
            _loanAmount = value;
            RaisePropertyChanged("LoanAmount");
        }
    }

    public double InterestRate
    {
        get
        {
            return _interestRate;
        }
        set
        {
            _interestRate = value;
            RaisePropertyChanged("InterestRate");
        }
    }

    public double Payment
    {
        get
        {
            return _payment;
        }
        set
        {
            _payment = value;
            RaisePropertyChanged("Payment");
        }
    }

    public double TotalInterest
    {
        get
        {
            return _totalInterest;
        }
        set
        {
            _totalInterest = value;
            RaisePropertyChanged("TotalInterest");
        }
    }

    public int Duration
    {
        get
        {
            return _duration;
        }
        set
        {
            _duration = value;
            RaisePropertyChanged("Duration");
        }
    }

    public ObservableCollection<PaymentInfo> Payments
    {
        get
        {
            return _payments;
        }
        set
        {
            _payments = value;
            RaisePropertyChanged("Payments");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

 

As you have noticed that we also implement INotifyPropertyChanged interface so I can do data binding. Then we define few auxiliary methods for our calculation.

Code Snippet
// Calculate the remaining balance at particular payment
double CalculateBalance(int month)
{
    double interestTerm = Math.Pow((1 + ad.InterestRate), month);
    double totalInterest = ad.LoanAmount * interestTerm;
    double totalPaid = ad.Payment * (interestTerm – 1) / ad.InterestRate;
    return totalInterest – totalPaid;
}

// Calculate the Interest part of any particular payment
double CalculateInterestPart(int month)
{
    double interestTerm = Math.Pow((1 + ad.InterestRate), (month – 1));
    double totalInterest = ad.LoanAmount * interestTerm;
    double totalPaid = ad.Payment * (interestTerm – 1) / ad.InterestRate;
    return (totalInterest – totalPaid) * ad.InterestRate;
}

// Calculate the principle part of any particular payment
double CalculatePrinciple(int month)
{
    return ad.Payment – CalculateInterestPart(month);
}

 

And then we are calling these methods in a loop to generate amortization schedule for all of our payments.

Code Snippet
// calculate interest term
int totalpayments = ad.Duration * 12;
ad.InterestRate /= 100;
ad.InterestRate /= 12;

double interestTerm = Math.Pow((1 + ad.InterestRate), totalpayments);

// calculate payment
ad.Payment = (ad.LoanAmount * ad.InterestRate) / (1 – (1 / interestTerm));

ad.TotalInterest = 0;
ad.Payments.Clear();

for (int iIndex = 1; iIndex <= totalpayments; ++iIndex)
{
    PaymentInfo paymentInfo = new PaymentInfo();
    paymentInfo.PaymentNo = iIndex;
    paymentInfo.Balance = CalculateBalance(iIndex);
    paymentInfo.Payment = ad.Payment;
    paymentInfo.Interest = CalculateInterestPart(iIndex);
    paymentInfo.Principle = CalculatePrinciple(iIndex);

    ad.TotalInterest += paymentInfo.Interest;

    ad.Payments.Add(paymentInfo);
}

 

It is very straight forward and there is no involvement of Mindscape library here. Then I created a simple interface with three tabs, one for the input, second for the amortization schedule and third one for the graph. I didn’t do anything special in the first two tabs other than do the binding of interest rate “OneWayToSource”. The main reason is that during the calculation when we divide the interest rate by 12 to get the monthly interest rate it should not update the user interface.

Now here comes the graph part.

Code Snippet
<ms:Chart Margin="5" Title="Amortization">
    <ms:BarSeries ItemsSource="{Binding}" SeriesBrush="Green"
                  XBinding="{Binding PaymentNo}"
                  YBinding="{Binding Principle}" />
    <ms:BarSeries ItemsSource="{Binding}" SeriesBrush="Red"
                  XBinding="{Binding PaymentNo}"
                  YBinding="{Binding Interest}"/>
</ms:Chart>

 

This one is quite straight forward and I just added these lines in a new tab of one of my existing program. Here is the output of the program after giving one input.

AmortizationGraph_01

This is a graph of multiple data series. So far so good. But now I want to set the legend of the graph. I want to see which one is for principle amount and which one for interest amount.

Here comes the interesting parts. I couldn’t figure out easily what should I do. Although there is a Legend class there in the help file, but its usage is not clear (at least to me). After some experiment I realized that the solution of this is even simpler than I thought. I just have to specity the name of the legend as a title property of the BarSeries class.

Code Snippet
<ms:Chart Margin="5" Title="Amortization">
    <ms:BarSeries ItemsSource="{Binding}" Title="Principle" SeriesBrush="Green"
                  XBinding="{Binding PaymentNo}"
                  YBinding="{Binding Principle}" />
    <ms:BarSeries ItemsSource="{Binding}" Title="Interest" SeriesBrush="Red"
                  XBinding="{Binding PaymentNo}"
                  YBinding="{Binding Interest}"/>
</ms:Chart>

 

Here is complete XAML code of our program.

Code Snippet
<Window x:Class="WpfAmortization.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        xmlns:ms="clr-namespace:Mindscape.WpfElements.Charting;assembly=Mindscape.WpfElements"
        Title="Loan Amortization" Height="350" Width="525">
    <Grid>
        <TabControl>
            <TabItem Header="Input">
                <Grid Margin="5">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <TextBlock Margin="5" Grid.Column="0" Grid.Row="0" VerticalAlignment="Center">Loan Amount</TextBlock>
                    <TextBox Margin="5" Grid.Column="1" Grid.Row="0" VerticalAlignment="Center" Text="{Binding LoanAmount}"/>
                    <TextBlock Margin="5" Grid.Column="0" Grid.Row="1" VerticalAlignment="Center">Interest Rate</TextBlock>
                    <TextBox Margin="5" Grid.Column="1" Grid.Row="1" VerticalAlignment="Center" Text="{Binding InterestRate, Mode=OneWayToSource}"/>
                    <TextBlock Margin="5" Grid.Column="0" Grid.Row="2" VerticalAlignment="Center">Number of years</TextBlock>
                    <TextBox Margin="5" Grid.Column="1" Grid.Row="2" VerticalAlignment="Center" Text="{Binding Duration}"/>
                    <TextBlock Margin="5" Grid.Column="0" Grid.Row="3" VerticalAlignment="Center">Payment</TextBlock>
                    <TextBlock Margin="5" Grid.Column="1" Grid.Row="3" VerticalAlignment="Center" Text="{Binding Payment}"/>
                    <Button Name="BtnClose" Margin="5" Grid.Column="0" Grid.Row="4" Click="Button_Close_Click">Close</Button>
                    <Button Name="BtnCalculate" Margin="5" Grid.Column="1" Grid.Row="4" Click="Button_Calculate_Click">Calculate</Button>
                </Grid>
            </TabItem>
            <TabItem Header="Amortization">
                <DataGrid Margin="5" AutoGenerateColumns="False" ItemsSource="{Binding Payments}">
                    <DataGrid.Columns>
                        <DataGridTextColumn Header="Payment No" Binding="{Binding PaymentNo}"/>
                        <DataGridTextColumn Header="Payment" Binding="{Binding Payment}"/>
                        <DataGridTextColumn Header="Principle" Binding="{Binding Principle}"/>
                        <DataGridTextColumn Header="Interest" Binding="{Binding Interest}"/>
                        <DataGridTextColumn Header="Balance" Binding="{Binding Balance}"/>
                    </DataGrid.Columns>
                </DataGrid>
            </TabItem>
            <TabItem Header="Graph" DataContext="{Binding Payments}">
                <ms:Chart Margin="5" Title="Amortization">
                    <ms:BarSeries ItemsSource="{Binding}" Title="Principle" SeriesBrush="Green"
                                  XBinding="{Binding PaymentNo}"
                                  YBinding="{Binding Principle}" />
                    <ms:BarSeries ItemsSource="{Binding}" Title="Interest" SeriesBrush="Red"
                                  XBinding="{Binding PaymentNo}"
                                  YBinding="{Binding Interest}"/>
                </ms:Chart>
            </TabItem>
        </TabControl>
    </Grid>
</Window>

 

And here is the output of the graph of this.

AmortizationGraph_02

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: