Question about casting.

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
Hey all so I figured I would post up my code and hopefully get some help here: The specific part I am having trouble with is when I try to cast the data back into an instance of my structure in order to display the information to the user here:
privatevoidListbox_SelectedIndexChanged(objectsender,EventArgse)
{
if(lstTransactions.SelectedIndex != -1)
{ //This underlined piece of code does not show any errors with the squiggly lines and the program compiles fine until I try to click on one of the entries in the listbox.
I get an exception thrown saying "Specified cast is not valid." Any help would be wonderful, this is a work in progress so there is code that I still need to write to finish this project but I need to get past this road block.
TransactionthisTransaction = (Transaction)lstTransactions.SelectedItem;
txtPayee.Text = thisTransaction.payee;
txtCheck.Text = thisTransaction.checkNumber;
txtAmount.Text = thisTransaction.Amount.ToString();
txtDate.Text = thisTransaction.Date.ToString();
switch(thisTransaction.Type)
{
case"Deposit":
rbDeposit.Checked =true;
break;
case"Withdrawal":
rbWithdrawal.Checked =true;
break;
case"Service Fee":
rbServiceFee.Checked =true;
break;
}
}
}using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Account_Balance
{
public partial class BalanceForm : Form
{
public BalanceForm()
{
InitializeComponent();
}

//Create a class to refer to different transaction types
enum transactionTypes
{ deposit, withdrawal, serviceFee }

//initialize form level variables
private decimal currentBalance = 0m,clearedBalance = 0m;
int currentIndex = 1;
Transaction[] record = new Transaction[21];

//Create a variable to store the transaction Type.
transactionTypes transType;

struct Transaction
{
public DateTime Date;
public string payee;
public decimal Amount;
public string Type;
public string checkNumber;
public string ToString(DateTime date, string type, decimal amount)
{
if (type != "Deposit")
return date.ToString("d").PadRight(13) + type.PadRight(21) + (amount * -1).ToString("C");
return date.ToString("d").PadRight(13) + type.PadRight(22) + amount.ToString("C");
}
}

//Display Header information.
private void DisplayHeader()
{
lstTransactions.Items.Add("Date".PadRight(13) + "Transaction Type".PadRight(22) + "Amount");
}

private void DisplayBalance()
{
lblCurrent.Text = currentBalance.ToString("C");
lblCleared.Text = clearedBalance.ToString("C");
}

private void Listbox_SelectedIndexChanged(object sender, EventArgs e)
{
if (lstTransactions.SelectedIndex != -1)
{
Transaction thisTransaction = (Transaction)lstTransactions.SelectedItem;
txtPayee.Text = thisTransaction.payee;
txtCheck.Text = thisTransaction.checkNumber;
txtAmount.Text = thisTransaction.Amount.ToString();
txtDate.Text = thisTransaction.Date.ToString();
switch (thisTransaction.Type)
{
case "Deposit":
rbDeposit.Checked = true;
break;
case "Withdrawal":
rbWithdrawal.Checked = true;
break;
case "Service Fee":
rbServiceFee.Checked = true;
break;
}
}
}

//Verify the funds available if type is a withdrawal
private bool isValidTransaction(decimal amount, transactionTypes type)
{
if (type == transactionTypes.withdrawal)
{
if (amount > currentBalance)
return false;
}
return true;
}

//Tag the radio buttons with the appropriate transaction type when the form loads
private void BalanceForm_Load(object sender, EventArgs e)
{
rbDeposit.Tag = transactionTypes.deposit;
rbServiceFee.Tag = transactionTypes.serviceFee;
rbWithdrawal.Tag = transactionTypes.withdrawal;
ClearData();
DisplayHeader();
}

private string SetType()
{
string type = "";
if (rbDeposit.Checked)
type = "Deposit";
else if (rbServiceFee.Checked)
type = "Service Fee";
else
type = "Withdrawal";
return type;
}
//Change the transaction type according to the radio button selected.
private void RadioButtons_CheckedChanged(object sender, EventArgs e)
{
RadioButton rb = (RadioButton)sender;
if (rb.Checked)
transType = (transactionTypes)rb.Tag;
}

//Confirm we have a valid date, return the actual date if valid, if invalid send back a date one day ahead of current date to signify an invalid date.
private DateTime isValidDate(string entry)
{
DateTime value;
if (DateTime.TryParse(entry, out value))
{
if (value > DateTime.Today)
value = DateTime.Today.AddDays(1);
}
else
value = DateTime.Today.AddDays(1);
return value;
}

//Confirm we have a valid amount, return the actual amount if valid, if invalid send back the amount as -1 to signify an invalid amount.
private decimal isValidAmount(string entry)
{
decimal value;
if (decimal.TryParse(entry, out value))
{
if (value <= 0)
value = -1;
}
else
value = -1;
return value;
}

//Confirm valid entries, if all are valid, return the amount. If any are invalid, display a message to user notifying them of the error
private decimal isValidEntries()
{
string message = "";
decimal amountEntry;
bool answer = true;
if (isValidDate(txtDate.Text)== DateTime.Today.AddDays(1))
{
answer = false;
message = "Please enter a valid date on or before today";
}
amountEntry = isValidAmount(txtAmount.Text);
if (amountEntry == -1)
{
answer = false;
message += "n" + "Amount must be a number greater than zero.";
}
if (rbWithdrawal.Checked)
{
if (txtPayee.Text == "")
{
answer = false;
message += "n" + "Payee must be entered for a Withdrawal";
}
}

if (answer)
{
if (!isValidTransaction(amountEntry, transType))
{
answer = false;
message = "Insufficient funds to complete this transaction.";
}
errorProvider1.Clear();
}
if (!answer)
{
amountEntry = -1;
errorProvider1.SetError(btnCalculate, message);
}
return amountEntry;
}

//All entries are valid at this point, determine the transaction type and calculate accordingly.
private void CalculateBalance(decimal amount)
{
if (transType != transactionTypes.deposit)
amount *= -1;
currentBalance += amount;
if (chkCleared.Checked)
clearedBalance += amount;
}

private void LoadArray()
{
record[currentIndex].Date = isValidDate(txtDate.Text);
record[currentIndex].Amount = isValidAmount(txtAmount.Text);
record[currentIndex].checkNumber = txtCheck.Text;
record[currentIndex].payee = txtPayee.Text;
record[currentIndex].Type = SetType();
currentIndex++;
}

//Update the cleared and current labels with the new balances for the user. Generate a list of transaction as the user makes them,
//keeping track of the date, amount, type, and if the transaction was processed.
private void DisplayData()
{
lstTransactions.Items.Add(record[currentIndex].ToString(isValidDate(txtDate.Text), SetType(), isValidAmount(txtAmount.Text)));
DisplayBalance();
}

private void ClearData()

{
//Clear all textboxes for another transaction entry and reset focus.
txtDate.Clear();
txtPayee.Clear();
txtCheck.Clear();
txtAmount.Clear();
txtAmount.Focus();
rbWithdrawal.Checked = true;
chkCleared.Checked = false;
}

private void btnReset_Click(object sender, EventArgs e)
{
//Reset the current balance back to zero and displaying this to the user.
currentBalance = 0m;
clearedBalance = 0m;
DisplayBalance();
lstTransactions.Items.Clear();
DisplayHeader();
ClearData();
}

private void btnClear_Click(object sender, EventArgs e)
{
//Clear all textboxes for another transaction entry and reset focus.
ClearData();
}

// Call the necessary procedures to valid all entries, set error messages (if needed), calculate balances and display balances.
private void btnCalculate_Click(object sender, EventArgs e)
{

decimal amount = isValidEntries();
if (amount != -1)
{
CalculateBalance(amount);
LoadArray();
DisplayData();
}
}

private void exitToolStripMenuItem1_Click(object sender, EventArgs e)
{
//Close this instance of the form.
this.Close();
}


}
}

View the full article
 
Back
Top