0

I'm creating an EPoS system for a university project but I've run into a brick wall with a piece of complex code concerning Event Arguments.

These pieces of code are on a Payment Form which handles the end of a transaction. I have declared the PaymentMadeEvent as so:

    public delegate void PaymentMadeEvent(object sender, paymentMadeEventArgs e);

    public event PaymentMadeEvent PaymentForm_PaymentMade;

Next I've declared a boolean value in a separate public class at the bottom of the code page as so:

public class paymentMadeEventArgs: EventArgs
{
    private bool paymentSuccess = true;

    public bool PaymentSuccess
    {
        get { return paymentSuccess; }
        set { paymentSuccess = value; }
    }
}

Next I've copied an example piece of code that handles the payment when it's entered:

private void PaymentHasBeenMade(object sender, EventArgs e)
    {

        try
        {
            total = decimal.Parse(txtBoxAmountToPay.Text) - decimal.Parse(txtBoxAmountTendered.Text);
        }
        catch
        {
            MessageBox.Show("An Error has occured, please enter a valid amount.");
            return;
        }

        if(total >0)
        {
            txtBoxAmountToPay.Text = String.Format("{0:c}", total);
        }
        else
        {
            MessageBox.Show("Please give " + String.Format("{0:c}", -total) + " in change.");
            PaymentForm_PaymentMade(this, new paymentMadeEventArgs(){ PaymentSuccess = true });
        }
    }

The error is a

System.NullReferenceException

which seems to be coming from this line here:

PaymentForm_PaymentMade(this, new paymentMadeEventArgs(){ PaymentSuccess = true });

Can anyone see what I'm doing wrong?

Thanks in advance.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
Tom Allen
  • 3
  • 1
  • 3
    Are you sure you have subscribers to your event? – Glorin Oakenfoot Mar 24 '16 at 16:54
  • 1
    `PaymentForm_PaymentMade` is `null` if noone has subcribed to that event. BTW: "seems to be coming from this line" is not a good way to ask on StackOverflow! An exception always has a stack trace that tells you _exactly_ where the error occurs. Please include this stack trace in your next question. – René Vogt Mar 24 '16 at 16:56
  • 1
    @DanielAWhite - As much as I love that dupe, its a bit harsh in this case, as this is a bit of a special case of a NRE – Jamiec Mar 24 '16 at 16:56
  • Daniel, any chance of linking me to said question? I've been trying to find an hour for almost 4 hours now and have come up empty handed. Glorin, I have, there are four buttons on the form which use this event. – Tom Allen Mar 24 '16 at 16:58
  • http://stackoverflow.com/questions/24640994/trouble-with-raising-custom-event-handling-between-2-forms/24641095#24641095 would have perhaps been a better duplicate – Jamiec Mar 24 '16 at 17:03

1 Answers1

0

Events are null until they have subscribers, so you need

if(PaymentForm_PaymentMade != null)
    PaymentForm_PaymentMade(this,new paymentMadeEventArgs(){ PaymentSuccess = true })

This is the origin of a particular pattern of code, which starts with not repeating the name of your form in the event name:

public event PaymentMadeEvent PaymentMade;

And having an On<EventName> method, commonly protected.

protected void OnPaymentMade(PaymentMadeEventArgs e)
{
    if(this.PaymentMade != null)
         this.PaymentMade(this,e);
}

Then you dont have to soil your code all over with if(...)

if(total >0)
{
    txtBoxAmountToPay.Text = String.Format("{0:c}", total);
}
else
{
    MessageBox.Show("Please give " + String.Format("{0:c}", -total) + " in change.");
    OnPaymentMade(new PaymentMadeEventArgs(){ PaymentSuccess = true });
}
Jamiec
  • 133,658
  • 13
  • 134
  • 193
  • Just for completeness, it is usually considered proper to store the event in a local variable before checking/invoking to prevent threading issues. For example: `PaymentMadeEvent LocalEvent = PaymentForm_PaymentMade; if(LocalEvent != null) ...` – Glorin Oakenfoot Mar 24 '16 at 16:58
  • 1
    @GlorinOakenfoot for full completeness: this pattern actually is obsolete with C#6, since you can now do `PaymentForm_PaymentMade?.Invoke(...)` – René Vogt Mar 24 '16 at 16:59
  • @RenéVogt - Good point. – Glorin Oakenfoot Mar 24 '16 at 17:02