I am currently trying to return an array which contains information about a seat at a theate such as Seat number, Name, Price and Status. I am using a combobox where I want to list all vacant or reserved seats based upon choice. When I choose reserved seats in my combobox, I call upon a method using AddRange. This method is supposed to loop through an array containing all seats and their information. If a seat is Vacant, I add it to an array. When all is done, I return this array. However, I am dealing with a ArgumentNullException.
MainForm:
namespace Assignment4
{
public partial class MainForm : Form
{
// private const int totNumberOfSeats = 240;
private SeatManager seatMngr;
private const int columns = 10;
private const int rows = 10;
public enum DisplayOptions
{
AllSeats,
VacantSeats,
ReservedSeats
}
public MainForm()
{
InitializeComponent();
seatMngr = new SeatManager(rows, columns);
InitializeGUI();
}
/// <summary>
/// Fill the listbox with information from the beginning,
/// let the user be able to choose from vacant seats.
/// </summary>
private void InitializeGUI()
{
rbReserve.Checked = true;
txtName.Text = string.Empty;
txtPrice.Text = string.Empty;
lblTotalSeats.Text = seatMngr.GetNumOfSeats().ToString();
cmbOptions.Items.AddRange(Enum.GetNames(typeof(DisplayOptions)));
cmbOptions.SelectedIndex = 0;
UpdateGUI();
}
/// <summary>
/// call on methods ValidateName and ValidatePrice with arguments
/// </summary>
/// <param name="name"></param>
/// <param name="price"></param>
/// <returns></returns>
private bool ValidateInput(out string name, out double price)
{
bool nameOK = ValidateName(out name);
bool priceOK = ValidatePrice(out price);
return nameOK && priceOK;
}
/// <summary>
/// Validate name using inputUtility, show error if input is invalid
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
private bool ValidateName(out string name)
{
name = txtName.Text.Trim();
if (!InputUtility.ValidateString(name))
{
//inform user
MessageBox.Show("Input of name is Invalid. It can not be empty, " + Environment.NewLine + "and must have at least one character.", " Error!");
txtName.Focus();
txtName.Text = " ";
txtName.SelectAll();
return false;
}
return true;
}
/// <summary>
/// Validate price using inputUtility, show error if input is invalid
/// </summary>
/// <param name="price"></param>
/// <returns></returns>
private bool ValidatePrice(out double price)
{
// show error if input is invalid
if (!InputUtility.GetDouble(txtPrice.Text.Trim(), out price, 0))
{
//inform user
MessageBox.Show("Input of price is Invalid. It can not be less than 0, " + Environment.NewLine + "and must not be empty.", " Error!");
txtPrice.Focus();
txtPrice.Text = " ";
txtPrice.SelectAll();
return false;
}
return true;
}
/// <summary>
/// Check if item is selected in listbox
/// </summary>
/// <returns></returns>
private bool CheckSelectedIndex()
{
int index = lbSeats.SelectedIndex;
if (index < 0)
{
MessageBox.Show("Please select an item in the box");
return false;
}
else
return true;
}
/// <summary>
/// Call method ReserveOrCancelSeat when button OK is clicked
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnOK_Click(object sender, EventArgs e)
{
ReserveOrCancelSeat();
}
/// <summary>
/// Reserve or cancel seat depending on choice the user makes. Update GUI after choice.
/// </summary>
private void ReserveOrCancelSeat()
{
if (CheckSelectedIndex() == true)
{
string name = string.Empty;
double price = 0.0;
int selectedSeat = lbSeats.SelectedIndex;
bool reserve = false;
bool cancel = false;
if (rbReserve.Checked)
{
DialogResult result = MessageBox.Show("Do you want to continue?", "Approve", MessageBoxButtons.YesNo);
if (result == DialogResult.Yes)
{
if (ValidateInput(out name, out price))
{
reserve = seatMngr.ReserveSeat(name, price, selectedSeat);
if (reserve == true)
{
MessageBox.Show("Seat has been reserved");
UpdateGUI();
}
else
{
MessageBox.Show("Seat has already been reserved");
}
}
}
}
else
{
DialogResult result = MessageBox.Show("Do you want to continue?", "Approve", MessageBoxButtons.YesNo);
if (result == DialogResult.Yes)
{
cancel = seatMngr.CancelSeat(selectedSeat);
if (cancel == true)
{
MessageBox.Show("Seat has been cancelled");
UpdateGUI();
}
else
{
MessageBox.Show("Seat is already vacant");
}
}
}
UpdateGUI();
}
}
/// <summary>
/// Update GUI with new information.
/// </summary>
/// <param name="customerName"></param>
/// <param name="price"></param>
private void UpdateGUI()
{
lbSeats.Items.Clear();
lbSeats.Items.AddRange(seatMngr.GetSeatInfoString());
lblVacantSeats.Text = seatMngr.GetNumOfVacant().ToString();
lblReservedSeats.Text = seatMngr.GetNumOfReserved().ToString();
if (rbReserve.Checked)
{
txtName.Text = string.Empty;
txtPrice.Text = string.Empty;
}
}
/// <summary>
/// set textboxes to false if cancel reservation button is checked
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void rbCancel_CheckedChanged_1(object sender, EventArgs e)
{
txtName.Enabled = false;
txtPrice.Enabled = false;
}
/// <summary>
/// set textboxes to true if reserved radiobutton is checked
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void rbReserve_CheckedChanged_1(object sender, EventArgs e)
{
txtName.Enabled = true;
txtPrice.Enabled = true;
}
/// <summary>
/// Make necessary changes on the list depending on what choice the user makes. Show only
/// what the user wants to see, whether its all seats, reserved seats or vacant seats only.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void cmbOptions_SelectedIndexChanged(object sender, EventArgs e)
{
if (cmbOptions.SelectedIndex == 0 && rbReserve.Checked) //All seats visible.
{
UpdateGUI();
txtName.Enabled = true;
txtPrice.Enabled = true;
btnOK.Enabled = true;
}
else if (cmbOptions.SelectedIndex == 0 && rbCancel.Checked)
{
UpdateGUI();
txtName.Enabled = false;
txtPrice.Enabled = false;
btnOK.Enabled = true;
}
else if (cmbOptions.SelectedIndex == 1) //Only vacant seats visible.
{
lbSeats.Items.Clear();
lbSeats.Items.AddRange(seatMngr.ReturnVacantSeats()); // Value cannot be null
txtName.Enabled = false;
txtPrice.Enabled = false;
btnOK.Enabled = false;
}
else if (cmbOptions.SelectedIndex == 2) //Only reserved seats visible.
{
lbSeats.Items.Clear();
lbSeats.Items.AddRange(seatMngr.ReturnReservedSeats()); // Value cannot be null
txtName.Enabled = false;
txtPrice.Enabled = false;
btnOK.Enabled = false;
}
}
}
}
SeatManager:
namespace Assignment4
{
class SeatManager
{
private string[,] nameList = null;
private double[,] priceList = null;
private string[,] seatList = null;
private readonly int totCols;
private readonly int totRows;
/// <summary>
/// Constructor with declarations of size for all arrays.
/// </summary>
/// <param name="totNumberOfSeats"></param>
public SeatManager(int row, int cols)
{
totCols = cols;
totRows = row;
nameList = new string[row, cols];
priceList = new double[row, cols];
seatList = new string[row, cols];
for (int rows = 0; rows < row; rows++)
{
for (int col = 0; col < totCols; col++)
{
seatList[rows, col] = "Vacant";
}
}
}
}
}
/// <summary>
/// Check if index is within bounds of the array
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
private bool CheckIndex(int index)
{
if (index >= 0 && index < nameList.Length)
return true;
else
return false;
}
/// <summary>
/// Return total number of seats
/// </summary>
/// <returns></returns>
public int GetNumOfSeats()
{
int count = 0;
for (int rows = 0; rows < totRows; rows++)
{
for (int cols = 0; cols < totCols; cols++)
{
count++;
}
}
return count;
}
/// <summary>
/// Calculate and return total number of reserved seats
/// </summary>
/// <returns></returns>
public int GetNumOfReserved()
{
int totReservedSeats = 0;
for (int rows = 0; rows < totRows; rows++)
{
for (int col = 0; col < totCols; col++)
{
if (!string.IsNullOrEmpty(nameList[rows, col]))
{
totReservedSeats++;
}
}
}
return totReservedSeats;
}
/// <summary>
/// Calculate and return total number of vacant seats
/// </summary>
/// <returns></returns>
public int GetNumOfVacant()
{
int totVacantSeats = 0;
for (int rows = 0; rows < totRows; rows++)
{
for (int col = 0; col < totCols; col++)
{
if (string.IsNullOrEmpty(nameList[rows, col]))
{
totVacantSeats++;
}
}
}
return totVacantSeats;
}
/// <summary>
/// Return formated string with info about the seat, name, price and its status
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public string GetSeatInfoAt(int index)
{
int cols = ReturnColumn(index);
int rows = ReturnRow(index);
string strOut = string.Format("{0,2} {1,10} {2,17} {3,20} {4,35:f2}",
rows+1, cols+1, seatList[rows, cols], nameList[rows, cols], priceList[rows, cols]);
return strOut;
}
/// <summary>
/// Send an array containing all seats in the cinema
/// </summary>
/// <returns></returns>
public string[] GetSeatInfoString()
{
int count = totRows * totCols;
if (count <= 0)
return null;
string[] strSeatInfoStrings = new string[count];
for (int i = 0; i < totRows * totCols; i++)
{
strSeatInfoStrings[i] = GetSeatInfoAt(i);
}
return strSeatInfoStrings;
}
/// <summary>
/// Reserve seat if seat is vacant
/// </summary>
/// <param name="name"></param>
/// <param name="price"></param>
/// <param name="index"></param>
/// <returns></returns>
public bool ReserveSeat(string name, double price, int index)
{
int cols = ReturnColumn(index);
int rows = ReturnRow(index);
if (string.IsNullOrEmpty(nameList[rows, cols]))
{
nameList[rows, cols] = name;
priceList[rows, cols] = price;
seatList[rows, cols] = "Reserved";
return true;
}
else
return false;
}
public string[] ReturnVacantSeats()
{
int totVacantSeats = int.Parse(GetNumOfVacant().ToString());
string[] vacantSeats = new string[totVacantSeats];
for (int i = 0; i < vacantSeats.Length; i++)
{
if (GetSeatInfoAt(i) == "Vacant")
{
vacantSeats[i] = GetSeatInfoAt(i);
}
}
return vacantSeats;
}
public string[] ReturnReservedSeats()
{
int totReservedSeats = int.Parse(GetNumOfReserved().ToString());
string[] reservedSeats = new string[totReservedSeats];
for (int i = 0; i < reservedSeats.Length; i++)
{
if (GetSeatInfoAt(i) == "Reserved")
{
reservedSeats[i] = GetSeatInfoAt(i);
}
}
return reservedSeats;
}
/// <summary>
/// Cancel seat if seat is reserved
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public bool CancelSeat(int index)
{
int cols = ReturnColumn(index);
int rows = ReturnRow(index);
if (!string.IsNullOrEmpty(nameList[rows, cols]))
{
nameList[rows, cols] = "";
priceList[rows, cols] = 0.0;
seatList[rows, cols] = "Vacant";
return true;
}
else
{
return false;
}
}
/// <summary>
/// Convert index to row and return value
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public int ReturnRow(int index)
{
int vectorRow = index;
int row;
row = (int)Math.Ceiling((double)(vectorRow / totCols));
return row;
}
/// <summary>
/// Convert index to column and return value
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public int ReturnColumn(int index)
{
int row = index;
int col = row % totCols;
return col;
}
In MainForm, this is where I get ArgumentNullException:
lbSeats.Items.AddRange(seatMngr.ReturnVacantSeats());
And this is the method where the array is to be returned containing all vacant seats:
public string[] ReturnVacantSeats()
{
int totVacantSeats = int.Parse(GetNumOfVacant().ToString());
string[] vacantSeats = new string[totVacantSeats];
for (int i = 0; i < vacantSeats.Length; i++)
{
if (GetSeatInfoAt(i) == "Vacant")
{
vacantSeats[i] = GetSeatInfoAt(i);
}
}
return vacantSeats;
}
wooolie,
The comments are indicating that you have the null problem due to the if
statement, therefore, you need to avoid adding values that contain null to your addrange call. Option #1 would be to change lbSeats.Items.AddRange(seatMngr.ReturnVacantSeats());
.
Here, you could add a `Where' clause along the lines of (untested code):
lbSeats.Items.AddRange(seatMngr.ReturnVacantSeats()
.Where(x => !string.IsNullOrEmpty(x)));
If you prefer not to do that, you can set the initial array up with default empty string values (this will prevent null exceptions).
option #2 (change):
string[] vacantSeats = new string[totVacantSeats];
to:
string[] vacantSeats = Enumerable.Repeat(string.Empty,totVacantSeats).ToArray();
messy frig, might work, might be total b@llocks, but might get you past the error for now.
The alternative of course (in current code) would be option #3:
if (GetSeatInfoAt(i) == "Vacant")
{
vacantSeats[i] = GetSeatInfoAt(i);
} else {
vacantSeats[i] = string.empty;
}
phew...