Wrox Programmer Forums

Need to download code?

View our list of code downloads.

Go Back   Wrox Programmer Forums > .NET > .NET 2.0 and Visual Studio. 2005 > .NET Framework 2.0
Password Reminder
Register
| FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read
.NET Framework 2.0 For discussion of the Microsoft .NET Framework 2.0.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the .NET Framework 2.0 section of the Wrox Programmer to Programmer discussions. This is a community of tens of thousands of software programmers and website developers including Wrox book authors and readers. As a guest, you can read any forum posting. By joining today you can post your own programming questions, respond to other developers’ questions, and eliminate the ads that are displayed to guests. Registration is fast, simple and absolutely free .
DRM-free e-books 300x50
Reply
 
Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old September 1st, 2008, 07:21 AM
Friend of Wrox
Points: 1,243, Level: 13
Points: 1,243, Level: 13 Points: 1,243, Level: 13 Points: 1,243, Level: 13
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Oct 2003
Location: , , United Kingdom.
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default HOW TO ADD AN EVENT HANDLER

Hi,

I am trying to improve my OO skills and as everyone else I am using a bank account class to learn some OO concepts such as encapsulation, usability etc...

Here is an extract of my Account class:

public class Account
{
    private decimal _balance;

        public Account(decimal initialAmount)
    {
       _balance = initialAmount;
    }

        public decimal Balance
    {
        get { return _balance; }
    }

        public void Withdraw(decimal amountToWithdraw)
    {... }

        public void Deposit(decimal amountToDeposit)
    {... }

}

This is how I call my class:

public partial class AccountForm : Form
{
   private const decimal _initialAmount = 300;
   private Account _account;

   public AccountForm()
   {
      _account = new Account(_initialAmount);
    DisplayBalance();
    statusLabel.Text = "Your account has been opened.";
   }

   private void DisplayBalance()
   {
    balanceValueLabel.Text = _account.Balance.ToString("C");
   }

   private void depositButton_Click(object sender, EventArgs e)
   {
       ....
    _account.Deposit(amountToDeposit);
    DisplayBalance();
    statusLabel.Text = "Amount has been deposited successfully.";
    }

    private void withdrawButton_Click(object sender, EventArgs e)
    {
    .......
        _account.Withdraw(amountToWithdraw);
    DisplayBalance();
    statusLabel.Text = "Amount has been withdrawn successfully.";
     }
}

This is all working fine. However, I would like to use an event handler as follows:

1- I would like to create an event to indicate changes in the Balance property.

2 - Then I would like to modify the form so that it uses this event to display the current balance (instead of using the DisplayBalance method after each button click).

I would appreciate very very much if someone could make changes to my sample code above and show me how to create an event and how to change the form to use the event.

Cheers

P
Reply With Quote
  #2 (permalink)  
Old September 2nd, 2008, 01:01 AM
Friend of Wrox
Points: 3,060, Level: 23
Points: 3,060, Level: 23 Points: 3,060, Level: 23 Points: 3,060, Level: 23
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Sep 2005
Location: , , .
Posts: 812
Thanks: 1
Thanked 53 Times in 49 Posts
Default

Hi

You can use Addhandler to handle .NET events (http://msdn.microsoft.com/en-us/libr...ka(VS.80).aspx)

http://dotnetdud.blogspot.com/2008/0...using-net.html

You can create your own events using (http://www.simple-talk.com/dotnet/.n...n-vb.net-2005/)

Cheers
Shasur

http://www.dotnetdud.blogspot.com

VBA Tips & Tricks (http://www.vbadud.blogspot.com)
Reply With Quote
  #3 (permalink)  
Old September 2nd, 2008, 09:02 AM
samjudson's Avatar
Friend of Wrox
Points: 8,687, Level: 40
Points: 8,687, Level: 40 Points: 8,687, Level: 40 Points: 8,687, Level: 40
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Aug 2007
Location: Newcastle, , United Kingdom.
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

You can implement the INotifyPropertyChanged interface on custom classes, and then use Data Binding to link your controls to your custom class instance.

/- Sam Judson : Wrox Technical Editor -/
Reply With Quote
  #4 (permalink)  
Old September 3rd, 2008, 07:37 AM
Friend of Wrox
Points: 1,243, Level: 13
Points: 1,243, Level: 13 Points: 1,243, Level: 13 Points: 1,243, Level: 13
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Oct 2003
Location: , , United Kingdom.
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

Hi Sam, Shasur,

Many thanks for your reply.

Sam, I was wondering if you could provide some sample code based on my Account class of how to implement the INotifyPropertyChanged interface.

I have the impression that the Balance property cannot be read only. Is my assupmtion right?

Cheers

P
Reply With Quote
  #5 (permalink)  
Old September 3rd, 2008, 07:44 AM
samjudson's Avatar
Friend of Wrox
Points: 8,687, Level: 40
Points: 8,687, Level: 40 Points: 8,687, Level: 40 Points: 8,687, Level: 40
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Aug 2007
Location: Newcastle, , United Kingdom.
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

You can simply follow the guidelines presented on the INotifyPropertyChanged documentation. The Balance property can be read only - but you have to then remember to raise the event when you change the underlying value, and not when you set the property.

http://msdn.microsoft.com/en-us/libr...tychanged.aspx

N.B. In C# 3.0 you can set a Property setter to have a different access modifier to a getter, i.e. you could set the 'set' for Balance to be private.
Code:
public class Account : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyChanged(string propertyName)
    {
        if( PropertyChanged != null )
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    private decimal _balance;

    public Account(decimal initialAmount)
    {
       _balance = initialAmount;
    }

    public decimal Balance
    {
        get { return _balance; }
    }

    public void Withdraw(decimal amountToWithdraw)
    {
        ...
        NotifyChanged("Balance");
    }

    public void Deposit(decimal amountToDeposit)
    {
        ... 
        NotifyChanged("Balance");
    }

}
/- Sam Judson : Wrox Technical Editor -/
Reply With Quote
  #6 (permalink)  
Old September 3rd, 2008, 09:27 AM
Friend of Wrox
Points: 1,243, Level: 13
Points: 1,243, Level: 13 Points: 1,243, Level: 13 Points: 1,243, Level: 13
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Oct 2003
Location: , , United Kingdom.
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

Hi Sam,

I will have a look at the link you provided. Also thanks for the sample code.

I have one question about your sample code.

You are raising the event handler inside the Deposit and Withdraw methods, right? So this meaans the event will be raised only when the user clicks the deposit or withdraw button in the user interface.

I thought it was better to raise the event when the Balance property changed itself. This way if the balance has been modified by an agent other than the user i.e. a new class that adds interest to an account balance at the start of each month then the balance would always be up to date.

Am I right in assuming that other agents rather than the user can also change the balance property?

How do we take care of that?

Cheers

P
Reply With Quote
  #7 (permalink)  
Old September 3rd, 2008, 09:32 AM
samjudson's Avatar
Friend of Wrox
Points: 8,687, Level: 40
Points: 8,687, Level: 40 Points: 8,687, Level: 40 Points: 8,687, Level: 40
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Aug 2007
Location: Newcastle, , United Kingdom.
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

No one else can modify the balance property because you have set it to read only - that's your decision, not mine. If you want others to modify it then add a setter, move the NotifyChange in there, and in the deposit and withdraw methods use "Balance" and NOT "_balance" to change the balance.

/- Sam Judson : Wrox Technical Editor -/
Reply With Quote
  #8 (permalink)  
Old September 3rd, 2008, 11:38 AM
Friend of Wrox
Points: 1,243, Level: 13
Points: 1,243, Level: 13 Points: 1,243, Level: 13 Points: 1,243, Level: 13
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Oct 2003
Location: , , United Kingdom.
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

Thanks,

I will try to do that....
Reply With Quote
  #9 (permalink)  
Old September 6th, 2008, 12:14 PM
Friend of Wrox
Points: 1,243, Level: 13
Points: 1,243, Level: 13 Points: 1,243, Level: 13 Points: 1,243, Level: 13
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Oct 2003
Location: , , United Kingdom.
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

Hi Sam,

I have tried the sample code you kindly provided to add an event handler to the Balance property but the PropertyChanged even is always evaluating to null and nothing happens when I try to make a deposit or withdraw.

Could you please have a look at my full code below (Account and AccountForm classes to see if you can spot where the problem is?

Cheers

ACCOUNT CLASS

using System;
using System.ComponentModel;

namespace Task
{
    public class Account: INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private void NofifyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this,new PropertyChangedEventArgs(propertyName));
            }
        }


        private decimal _balance;

        public Account(decimal initialAmount)
        {
            // use initialAmount to set the _balance field
            _balance = initialAmount;
        }


        public decimal Balance
        {
            get { return _balance; }
        }

        public void Withdraw(decimal amountToWithdraw)
        {
            if (amountToWithdraw <= 0)
                throw new ArgumentOutOfRangeException();

            if (_balance < amountToWithdraw)
                throw new InvalidOperationException();

            _balance -= amountToWithdraw;
            NofifyChanged("Balance");

        }

        public void Deposit(decimal amountToDeposit)
        {
            if (amountToDeposit <= 0)
                throw new ArgumentOutOfRangeException();

            _balance += amountToDeposit;
            NofifyChanged("Balance");
        }

    }
}

ACCOUNTFORM CLASS


using System;
using System.Windows.Forms;

namespace Task
{
    public partial class AccountForm : Form
    {
        private const decimal _initialAmount = 300;

        private Account _account;

        public AccountForm()
        {
            InitializeComponent();

            _account = new Account(_initialAmount);


            EnableButtons(false);
            DisplayBalance();
            statusLabel.Text = "Your account has been opened.";
        }

        private void DisplayBalance()
        {

                     balanceValueLabel.Text = _account.Balance.ToString();

        }

        private void depositButton_Click(object sender, EventArgs e)
        {
            decimal amountToDeposit;
            if (ValidateAmountInput(out amountToDeposit) == false)
                return;

            try
            {


                                _account.Deposit(amountToDeposit);

                //DisplayBalance();
                statusLabel.Text = "Amount has been deposited successfully.";
            }
            catch (Exception ex)
            {
                statusLabel.Text = ex.Message;
            }
        }

        private void withdrawButton_Click(object sender, EventArgs e)
        {
            decimal amountToWithdraw;
            if (ValidateAmountInput(out amountToWithdraw) == false)
                return;

            try
            {

                               _account.Withdraw(amountToWithdraw);

                //DisplayBalance();
                statusLabel.Text = "Amount has been withdrawn successfully.";
            }
            catch (Exception ex)
            {
                statusLabel.Text = ex.Message;
            }
        }

        private void amountText_TextChanged(object sender, EventArgs e)
        {

            EnableButtons(amountText.Text.Trim().Length > 0);
        }

        private void EnableButtons(bool enable)
        {

            depositButton.Enabled = enable;
            withdrawButton.Enabled = enable;
        }

        private bool ValidateAmountInput(out decimal value)
        {

            if (decimal.TryParse(amountText.Text, out value) == false)
            {
                statusLabel.Text = "The entered amount is not of decimal type.";
                amountText.Text = String.Empty;
                return false;
            }

            amountText.Text = String.Empty;
            return true;
        }
    }
}
Reply With Quote
  #10 (permalink)  
Old September 7th, 2008, 05:32 AM
samjudson's Avatar
Friend of Wrox
Points: 8,687, Level: 40
Points: 8,687, Level: 40 Points: 8,687, Level: 40 Points: 8,687, Level: 40
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Aug 2007
Location: Newcastle, , United Kingdom.
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

You have to actually then use data binding to hook the balance up with your textbox. The following should do that:

balanceValueLabel.DataBindings(new Binding("Text", _account, "Balance"));

/- Sam Judson : Wrox Technical Editor -/
Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Chapter 19, p.970, Can't Add Event Handler Spasticus BOOK: Ivor Horton's Beginning Visual C++ 2005 0 January 6th, 2008 05:13 PM
Event handler samir_katore Pro VB 6 6 June 8th, 2006 01:22 PM
Event handler problem carro123 Javascript How-To 1 May 20th, 2005 03:30 PM
PreDefined Event Handler mark C# 1 June 7th, 2003 04:47 AM



All times are GMT -4. The time now is 12:05 AM.


Powered by vBulletin®
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.