CheckListBox Updated from another CheckListBox - c#

I'm creating a form with two Checklistboxes. The first one is populated by a database query, while the latter is dinamically created when I check elements on the first one and these ones have to be replicated on the second one. The first works fine, while the second give me troubles, since it returns me always n-1 elements. I tried unsucessfully several methods, for instance BeginUpdate() and EndUpdate(), cblStaff..GetItemChecked(i)) instead of cblStaff.GetItemCheckState(i).Equals(CheckState.Checked).
I guess it's a matter of value refresh since I placed a label (lblCounter) to check how many items on cblStaff have been selected.
Maybe it's a matter of events, and I'm using the wrong one, but I'm getting crazy with this control.
This is the code:
private void cblStaff_ItemCheck(object sender, ItemCheckEventArgs e)
{
cblStaff.BeginUpdate();
switch (e.CurrentValue)
{
case CheckState.Indeterminate:
e.NewValue = CheckState.Checked;
break;
case CheckState.Checked:
e.NewValue = CheckState.Unchecked;
persons--;
break;
case CheckState.Unchecked:
e.NewValue = CheckState.Checked;
persons++;
break;
}
cblStaff.EndUpdate();
TeamUpdate();
}
private void RefreshDirector()
{
cblDirector.Items.Clear();
int counter = 0;
for (int i = 0; i < cblStaff.Items.Count; i++)
{
if (cblStaff.GetItemCheckState(i).Equals(CheckState.Checked)) {
cblDirector.Items.Add(cblStaff.Items[i].ToString(), CheckState.Unchecked);
counter++;
lblCounter.Text = "" + counter;
}
}
}
private void TeamUpdate()
{
switch (persons) {
case 0:
lblTeam.Text = "No team";
break;
case 1:
lblTeam.Text = "1 person team";
break;
default:
lblTeam.Text = "" + persons + " people team";
break;
}
cblStaff.Refresh();
RefreshDirector();
}

Related

c# - Console.Clear() don't clear text from other methods

I am making simple PRG in console.
In my MenuSystem Console.Clear() does not clear text from other methods.
Any ideas?
class MenuSystem
{
public static void Controll(int count, List<String> texts)
{
Console.Clear();
int index = 0;
bool isEnter = false;
Write(0, texts);
while (!isEnter)
{
ConsoleKey key = Console.ReadKey().Key;
switch (key)
{
case ConsoleKey.UpArrow:
index -= 1;
break;
case ConsoleKey.DownArrow:
index += 1;
break;
}
if (index > (count - 1))
index = 0;
else if (index < 0)
index = count - 1;
Write(index, texts);
}
}
private static void Write(int index, List<String> texts)
{
Console.Clear();
texts[index] = "[ " + texts[index] + " ]";
foreach (String text in texts)
{
Console.WriteLine(text);
}
}
Console.Clear() in Write() does not clear console.
I think the problem you're having is not with Console.Clear (whose only purpose is to clear the screen, not "clear text from other methods" as you suggested.
The problem is that you're modifying an element in your array, then modifying a new element in the array without un-modifying the previous one. If you wanted to solve this problem using your current method, then you would need to track which item you previously modified in a class-level variable so you can un-modify it when the user changes the selection.
However, I would suggest a different approach. Instead of modifying the strings in your list, you should just change the way you display the information, not the information itself.
So, after applying your logic to detect which index to select, you just loop through the menu items and write them to the screen, and when you get to the index of the item that's selected, you write the "[" and "]" characters around it. For the other menu items, you should surround them with an empty space character, so they aren't moving all over the place as the selections change.
Note that I also made a small change to have the menu display horizontally:
class MenuSystem
{
public static void Control(List<string> menuItems)
{
var selectedIndex = 0;
var exitMenu = false;
while (!exitMenu)
{
DisplayMenu(selectedIndex, menuItems);
switch (Console.ReadKey().Key)
{
case ConsoleKey.LeftArrow:
selectedIndex -= 1;
if (selectedIndex < 0) selectedIndex = menuItems.Count - 1;
break;
case ConsoleKey.RightArrow:
selectedIndex += 1;
if (selectedIndex > menuItems.Count - 1) selectedIndex = 0;
break;
case ConsoleKey.Enter:
exitMenu = true;
break;
}
}
}
private static void DisplayMenu(int selectedIndex, List<string> menuItems)
{
Console.Clear();
for (int i = 0; i < menuItems.Count; i++)
{
if (i == selectedIndex)
{
Console.Write("[" + menuItems[i] + "]");
}
else
{
Console.Write(" " + menuItems[i] + " ");
}
Console.Write(" ");
}
}
}
This is really an answer to your question but merely a demonstration that the code you have posted does work.
private static void Main()
{
Console.Write("Some Text");
Console.Read(); //Console shows Show Text
MenuSystem.Controll(1, new List<string>() { "string" });
Console.Read(); //Console shows string
}
...
class MenuSystem
{
public static void Controll(int count, List<String> texts)
{
Write(count, texts);
}
private static void Write(int index, List<String> texts) //I don't know why you are passing index as it is never used here.
{
Console.Clear(); //Console is now cleared
foreach (String text in texts)
{
Console.WriteLine(text);
}
}
}
As the code you have provided is working I can only presume that there is some other logic in your full code that is causing the issue.
Please update your question with code that demonstrates your issue.
The example is far from perfect, but you will get the sense of using Console.Clear():
class Program
{
static void DrawPlayer(int x, int y)
{
for (int i = 0; i < y; i++)
Console.WriteLine();
for (int j = 0; j < x; j++)
Console.Write(' ');
Console.Write("\u25A0");
}
static void Main()
{
int playerX = 0, playerY = 0;
while (true)
{
DrawPlayer(playerX, playerY);
var keyInfo = Console.ReadKey(true);
switch (keyInfo.Key)
{
case ConsoleKey.W:
playerY--;
break;
case ConsoleKey.A:
playerX--;
break;
case ConsoleKey.S:
playerY++;
break;
case ConsoleKey.D:
playerX++;
break;
}
Console.Clear();
}
}
}

Switch case goes to default except one case

when i tried to use the Switch case function, it goes always to the default message besides case 5:
private void btnCandlesLight_Click(object sender, EventArgs e)
{
int result;
result = Convert.ToInt32(textBox1.Text);
switch(result)
{
case 1:
day1.Start();
candlesOne();
break;
case 2:
day2.Start();
candlesTwo();
break;
case 3:
day3.Start();
candlesThree();
break;
case 4:
day4.Start();
candlesFour();
break;
case 5:
day5.Start();
candlesFive();
break;
case 6:
day6.Start();
candlesSix();
break;
case 7:
day7.Start();
candlesSeven();
break;
case 8:
day8.Start();
candlesEight();
break;
default:
MessageBox.Show("Enter new day");
break;
}
}
When I Enter the value 1 for example to the text box, the default case works, but only when I enter the value 5 it works perfectly.
If you want to see the difference between the function "candlesOne" to "candlesFive":
The "c" variable is a variable of the seconds. i tried to use a timer in a way of lighting up the candles every 2-3 seconds.
public void candlesOne()
{
firedmatch.Left = firedmatch.Left + 100;
if (c == 1)
{
candle1.Visible = true;
}
if (c == 3)
{
candle2.Visible = true;
}
}
and:
public void candlesFive()
{
firedmatch.Left = firedmatch.Left + 100;
if(c == 1)
{
candle1.Visible = true;
}
if(c == 3)
{
candle2.Visible = true;
}
if(c == 5)
{
candle3.Visible = true;
}
if(c == 7)
{
candle4.Visible = true;
}
if(c == 11)
{
candle5.Visible = true;
}
}
I haven't found a mistake,
can you guys help me?
Thanks
Have you checked if you really get for example (int)1 as a result of the "1" input from your conversion?
On a broader scale, there is a lot of repetition in your code, you should consider refactoring it a little.
In your CandlesOne and CandlesFive methods, you use a c variable, no idea what that is or where it comes from. Those two methods (and probably the other CandlesXXX() do the same kind of things. Can't you remove complexity by generalizing the logic? Can the result used in your switch-case be passed as a parameter and used to trigger the numbers of c == X calls in the CandleXXX() methods?
This way you could remove the switch and lose a lot of complexity!
Edit
If you have further problems, consider creating a .NET Fiddle, I miss a lot of context in your code so I cannot efficiently help you here.
Some refactoring ideas for you:
// Somewhere else in your code, create a dictionary with your day1-day8 objects
var days = new Dictionary<int, Day>()
days[1] = day1;
...
days[8] = day8;
//Simplfiy your method
private void btnCandlesLight_Click(object sender, EventArgs e)
{
try
{
var dayIndex = Convert.ToInt32(textBox1.Text);
if(dayIndex > 0 && dayIndex <= 8)
{
days[dayIndex].Start(); //Get the corresponding day via its Key
LightUpCandles(dayIndex); //pass the key as a parameter
}
else
{
MessageBox.Show("Enter new day");
}
}
catch(InvalidCastException exception)
{
//Whatever you do when the textbox cannot be parsed
}
}
I still don't get what your candlesOne to five methods are really doing or why the method "candlesOne" lights up two candles (pay attention to the variable naming). I also don't get how this makes up some kind of timer... but here's a first potential refactoring for it anyway:
public void LightUpCandles(int dayIndex)
{
firedmatch.Left = firedmatch.Left + 100;
if(c == 1)
{
candle1.Visible = true;
}
if(c == 3 && dayIndex > 1)
{
candle2.Visible = true;
}
if(c == 5 && dayIndex > 2)
{
candle3.Visible = true;
}
if(c == 7 && dayIndex > 3)
{
candle4.Visible = true;
}
if(c == 11 && dayIndex > 4)
{
candle5.Visible = true;
}
}
Your switch logic is correct which I tested with the following;
int result;
result = Convert.ToInt32(textBox1.Text);
switch (result)
{
case 1:
MessageBox.Show("1");
break;
case 2:
MessageBox.Show("2");
break;
case 3:
MessageBox.Show("3");
break;
case 4:
MessageBox.Show("4");
break;
case 5:
MessageBox.Show("5");
break;
case 6:
MessageBox.Show("6");
break;
case 7:
MessageBox.Show("7");
break;
case 8:
MessageBox.Show("8");
break;
default:
MessageBox.Show("Enter new day");
break;
}
If you don't get the same results I would perhaps look at making the message boxes above display the data type of the variable.
MessageBox.Show(result.GetType().ToString());

C# TextBox Override Arrow Key Select Function

Basically, continuing from this question, when the user presses shift + either left or right I need it to select the entire character group.
The current code I have (under the PreviewKeyDown Event):
string s;
int caretLocation = textBox1.SelectionStart;
string txt = textBox1.Text;
if (e.Shift)
{
switch (e.KeyCode)
{
#region Right
case Keys.Right:
{
s = txt.Substring(caretLocation);
foreach (string combo in charCombinations)
{
if (s.StartsWith(combo))
{
textBox1.SelectionLength = combo.Length - 1;
break;
}
}
break;
}
#endregion
#region Left
case Keys.Left:
{
s = txt.Substring(0, caretLocation);
foreach (string combo in charCombinations)
{
if (s.EndsWith(combo))
{
textBox1.SelectionStart = caretLocation - combo.Length + 1;
textBox1.SelectionLength = combo.Length + 1
break;
}
}
break;
}
#endregion
}
}
The first issue lies with the right key, where if there are two of such character groups in a row, the caret does not move right any further from the position shown below:
The second issue lies with the left key, where the left key selection just doesn't select the entire character:
For this case, the entire word sin( should be selected.
Thanks in advance!
charCombinations has been defined as:
private static readonly string[] charCombinations = new string[] { "asinh(", "acosh", "atanh(",
"sinh(", "cosh(", "tanh(", "asin(", "acos(", "atan(", "sin(", "cos(", "tan(",
"log(", "ln(", "PI", "e", "Phi"};
You must add next text length to previous length.
I fixed your codes this model:
case Keys.Right:
{
s = txt.Substring(caretLocation);
foreach (string combo in charCombinations)
{
if (s.StartsWith(combo))
{
textBox1.SelectionLength += combo.Length - 1;
break;
}
}
break;
}
The important line is: textBox1.SelectionLength += combo.Length - 1;
in that I use += instead =

Issue with too expensive search txt store to datatable - hanging WinForm GUI - Foreach+Switch vs. something?

*updated with suggestions, but still taking time... started at 7 days of processing, now its taking 2,5 days. DataTableAdapter access is taking huge time.
I'm neewbie but intensive-researcher in stackoverflow, even so, couldn't find any answers that fit my problem.
I have 80 files, each with 200,000 lines - with little 'standards' or TAG's in format.
I've been able to search through each file, each line, and just replaced a IF-ELSE to a SWITCH-CASE (it improved performance, thanks to stackoverflow forum) and put intensive-stuff into another thread (again stackoverflow user's merit).
Even so, I'm getting 95 minutes per file, witch takes me to a 2,5 days-text-processing, and when deployed, I get a hang GUI (in debug its okay).
The txt file has this standard, with variable lines, :
BARR; --> thats first tag
184071; ALAMEDOS ; 518042,100; 922453,700; --> thats valid information I want
TAGs are (full line on txt): SE; -> CKT; -> BARR; -> TRECH; -> CAP; -> INST; -> KEY; -> REG; -> ET;xxxx; -> EP;xxxx; -> DMD; -->but can skip some "tags" without notice, thats why I'm testing line by line
My problem:
- 2,5 days of intensive processing; (critical)
- hanging gui after deployment; (not that bad, could solve later)
(thanks in advace!)
My winform click action - calling thread and the backgroundworker with the intensive stuff: (tried to wrap-up because its lenghty..)
`private void Button_extract_element_Click(object sender, EventArgs e)
{
TestObject test = new TestObject();
test._shouldstop = true;
backgroundWorker1.RunWorkerAsync(test);
int passes = 0;
Label_extract_element.Text = "wait processing....";
Label_extract_element.Refresh();
Label_extract_element.Update();
//this should keep winform waiting for thread-return, showing passes
while (test._shouldstop)
{
passes++;
Label_extract_element.Text = "wait processing...." + passes;
Label_extract_element.Refresh();
Label_extract_element.Update();
}
Label_extract_element.Text = " OK, done!";
Label_extract_element.Refresh();
Label_extract_element.Update();
} //End of Button_extract_element_Click
class TestObject
{
public bool _shouldstop { get; set; }
}
//backgroundWorker complete actions
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Receive the result from DoWork, and display it.
TestObject test = e.Result as TestObject;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
TestObject argumentTest = e.Argument as TestObject;
argumentTest._shouldstop = true;
string loop = "";
string[] ListOfFilesinDir = Directory.GetFiles(GlobalVariables.folder, "*.txt").Select(Path.GetFileName).ToArray();
foreach (string filename in ListOfFilesinDir)
{
int count_barr = 0;
int count_lines = 0;
//ReadAll seems to process really fast - not a gap
string[] FLines = File.ReadAllLines(GlobalVariables.folder + "\\" + filename);
int[] line_barr = new int[FLines.Count()];
foreach (string Lines in FLines)
{
count_lines++;
switch (Lines)
{
case "SE;":
GlobalVariables.SEstr = FLines[count_lines].Split(';')[3].Trim();
break;
case "CKT;":
GlobalVariables.codCktAL = FLines[count_lines].Split(';')[2].Trim();
GlobalVariables.nomeCktAL = FLines[count_lines].Split(';')[10].Trim();
GlobalVariables.nomeArqv = filename;
break;
case "BARR;": loop = "BARR;"; break;
case "TRECH;": loop = "TRECH;"; break;
case "CAP;": loop = "CAP;"; break;
case "INST;": loop = "INST;"; break;
case "KEY;": loop = "KEY;"; break;
case "REG;": loop = "REG;"; break;
case "DMD;":
loop = "DMD;";
GlobalVariables.TRAFO = (FLines[count_lines-8].Split(';')[1].Trim());
break;
}
switch (loop)
{
// I'll post just the first case, so I dont go soooo long in this post..
//This part seems to process really fast
case "BARR;":
GlobalVariables.parse_results = "";
//take next line and test if is one of the nexts TAGs, and break loop:
GlobalVariables.parse_results += FLines[count_lines];
if (Equals(GlobalVariables.parse_results, "TRECH;") || Equals(GlobalVariables.parse_results, "CAP;") || Equals(GlobalVariables.parse_results, "INST;") || Equals(GlobalVariables.parse_results, "KEY;") || Equals(GlobalVariables.parse_results, "REG;") || Equals(GlobalVariables.parse_results.Split(';')[0], "ET") || Equals(GlobalVariables.parse_results.Split(';')[0], "EP"))
{
GlobalVariables.parse_results = "";
loop = "";
break;
}
else //initiates the extraction BARR just have 4 field in txt
{
//save the number of the line to array for later reference
count_barr++;
line_barr[count_barr] = count_lines;
break;
}
case "TRECH;": /*repeat all in BARR loop for TRECH's 20 fields*/ break;
case "CAP;": /*same repeat for different n fields*/ break;
case "INST;": /*same repeat for different n fields*/ break;
case "KEY;": /*same repeat for different n fields*/ break;
case "REG;": /*same repeat for different n fields*/ break;
} //end of switch
} //end for each lines
//Now the TAKING TIME: saving to database - take the line number reference stored
for (int i = 1; i < (count_barr+1); i++)
{
double p0 = Convert.ToDouble(FLines[line_barr[i]].Split(';')[0].Trim());
string p1 = FLines[line_barr[i]].Split(';')[1].Trim().ToString();
double p2 = Convert.ToDouble(FLines[line_barr[i]].Split(';')[2].Trim());
double p3 = Convert.ToDouble(FLines[line_barr[i]].Split(';')[3].Trim());
barr_MTTableAdapter1.GRAVA(p0, p1, p2 , p3, GlobalVariables.SEstr, GlobalVariables.codCktAL, GlobalVariables.nomeCktAL, GlobalVariables.nomeArqv);
}
argumentTest._shouldstop = false;
e.Result = argumentTest;
}`
Your answer still is problematic. Use the following example to not read all lines into memory:
System.IO.StreamReader file =
new System.IO.StreamReader("c:\\test.txt");
while((line = file.ReadLine()) != null)
{
Console.WriteLine (line);
counter++;
}
There is no need for a tiny file like yours to take that long. I process files with about half a billion events (granted, those are binary coded, but waaaaaaay more than your 200.000 lines) in minutes. You're wasting lots of time by doing things like allocating an array of lines instead of reading the files line by line.
As stated in question, this answer only applies to MS Access Database, if you use Oracle or SQL Server just launch a Bulk load
Well, after a lot of contributions (see comments above specially from Voo) and a lot of stackoverflow research, I could improve the performance from 7 days to 45 minutes processing total 16 million lines, line-by-line.
The key after well-oriented tips from people in comments, was to use DAO (with some worries about deployment the database with ClickOnce - notice the dbName connection string).
A lot of usefull information can be found here:
StackOverflow-Writing-large-records
If you use accdb, you need to do a modification in using ADO to:
using DAO = Microsoft.Office.Interop.Access.Dao;
(can be found in Visual Studio add reference in COM Type references, you need to add the Microsoft Office xx.x Access Database Engine Object Library - but remember that this imposes a great limitation to your end-user specs.
I noticed some improvements needed to store all iterations in DAO (BARR, TRECH, so on..) but its code-optimization, not the main issue in this post.
Dont know the reason why .NET doenst add a bulk insert for MS Access.
The code above for each file, takes 0.3 seconds to pass switch statments, and 1.33 minutes to DAO-saving. If doing for all 80 files takes 45 minutes
private void Button_extract_element_Click(object sender, EventArgs e)
{
TestObject test = new TestObject();
test._shouldstop = true;
backgroundWorker1.RunWorkerAsync(test);
int passes = 0;
Label_extract_element.Text = "wait processing....";
Label_extract_element.Refresh();
Label_extract_element.Update();
//this should keep winform waiting for thread-return, showing passes
while (test._shouldstop)
{
passes++;
Label_extract_element.Text = "wait processing...." + passes;
Label_extract_element.Refresh();
Label_extract_element.Update();
}
Label_extract_element.Text = " OK, done!";
Label_extract_element.Refresh();
Label_extract_element.Update();
} //End of Button_extract_element_Click
class TestObject
{
public bool _shouldstop { get; set; }
}
//backgroundWorker complete actions
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Receive the result from DoWork, and display it.
TestObject test = e.Result as TestObject;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
TestObject argumentTest = e.Argument as TestObject;
argumentTest._shouldstop = true;
string loop = "";
string[] ListOfFilesinDir = Directory.GetFiles(GlobalVariables.folder, "*.txt").Select(Path.GetFileName).ToArray();
foreach (string filename in ListOfFilesinDir)
{
int count_barr = 0;
int count_lines = 0;
//ReadAll seems to process really fast - not a gap
string[] FLines = File.ReadAllLines(GlobalVariables.folder + "\\" + filename);
int[] line_barr = new int[FLines.Count()];
foreach (string Lines in FLines)
{
count_lines++;
switch (Lines)
{
case "SE;":
GlobalVariables.SEstr = FLines[count_lines].Split(';')[3].Trim();
break;
case "CKT;":
GlobalVariables.codCktAL = FLines[count_lines].Split(';')[2].Trim();
GlobalVariables.nomeCktAL = FLines[count_lines].Split(';')[10].Trim();
GlobalVariables.nomeArqv = filename;
break;
case "BARR;": loop = "BARR;"; break;
case "TRECH;": loop = "TRECH;"; break;
case "CAP;": loop = "CAP;"; break;
case "INST;": loop = "INST;"; break;
case "KEY;": loop = "KEY;"; break;
case "REG;": loop = "REG;"; break;
case "DMD;":
loop = "DMD;";
GlobalVariables.TRAFO = (FLines[count_lines-8].Split(';')[1].Trim());
break;
}
switch (loop)
{
// I'll post just the first case, so I dont go soooo long in this post..
//This part seems to process really fast
case "BARR;":
GlobalVariables.parse_results = "";
//take next line and test if is one of the nexts TAGs, and break loop:
GlobalVariables.parse_results += FLines[count_lines];
if (Equals(GlobalVariables.parse_results, "TRECH;") || Equals(GlobalVariables.parse_results, "CAP;") || Equals(GlobalVariables.parse_results, "INST;") || Equals(GlobalVariables.parse_results, "KEY;") || Equals(GlobalVariables.parse_results, "REG;") || Equals(GlobalVariables.parse_results.Split(';')[0], "ET") || Equals(GlobalVariables.parse_results.Split(';')[0], "EP"))
{
GlobalVariables.parse_results = "";
loop = "";
break;
}
else
{
//store the number of the line to array for later reference
count_barr++;
line_barr[count_barr] = count_lines;
break;
}
case "TRECH;": /*repeat all in BARR loop for TRECH's 20 fields*/ break;
case "CAP;": /*same repeat for different n fields*/ break;
case "INST;": /*same repeat for different n fields*/ break;
case "KEY;": /*same repeat for different n fields*/ break;
case "REG;": /*same repeat for different n fields*/ break;
} //end of switch
} //end for each lines
string dbName = Application.StartupPath + "\\Resources";
DAO.DBEngine dbEngine = new DAO.DBEngine();
DAO.Database db = dbEngine.OpenDatabase(dbName+"\\DataBase.accdb");
// From here, could work more to store different Tables with different fields, dynamically, improving code
DAO.Recordset rs = db.OpenRecordset("BARRA_MT");
for (int i = 1; i < (count_barr+1); i++)
{
rs.AddNew();
double b0 = Convert.ToDouble(FLines[line_barr[i]].Split(';')[0].Trim());
string b1 = FLines[line_barr[i]].Split(';')[1].Trim().ToString();
double b2 = Convert.ToDouble(FLines[line_barr[i]].Split(';')[2].Trim());
double b3 = Convert.ToDouble(FLines[line_barr[i]].Split(';')[3].Trim());
rs.Fields["BARR_MT"].Value = b0;
rs.Fields["COD"].Value = b1;
rs.Fields["X"].Value = b2;
rs.Fields["Y"].Value = b3;
rs.Update();
}
rs.Close();
db.Close();
argumentTest._shouldstop = false;
e.Result = argumentTest;
} //end`

Listbox unassigned variable

Full disclosure here, I am a student doing homework. I have 2 listboxes with items that can be selected. What is said in them is not needed to be extracted. I wrote the code out and everything works except I get an error saying "use of unassigned variable" on 3 variables at the end of the code. They are locFees, days, and registration. Can anyone tell me what I am doing wrong that is causing the variables to not have a value?
private void btnCalc_Click(object sender, EventArgs e)
{
double registration, lodging, total, days, locFees;
int workshopIndex, locationIndex;
if (lbWorkshop.SelectedIndex != -1)
{
workshopIndex = lbWorkshop.SelectedIndex;
switch (workshopIndex)
{
case 0:
days = 3;
registration = 1000;
break;
case 1:
days = 3;
registration = 800;
break;
case 2:
days = 3;
registration = 1500;
break;
case 3:
days = 5;
registration = 1300;
break;
case 4:
days = 1;
registration = 500;
break;
}
}
else
{
MessageBox.Show("You didn't select a workshop.");
}
if (lbLocation.SelectedIndex != -1)
{
locationIndex = lbLocation.SelectedIndex;
switch (locationIndex)
{
case 0:
locFees = 150;
break;
case 1:
locFees = 225;
break;
case 2:
locFees = 175;
break;
case 3:
locFees = 300;
break;
case 4:
locFees = 175;
break;
case 5:
locFees = 150;
break;
}
}
else
{
MessageBox.Show("You didn't select a city.");
}
lodging = locFees * days;
total = registration + lodging;
}
Can anyone tell me what I am doing wrong that is causing the variables to not have a value?
Sure - you're ignoring the possibility that workshopIndex isn't 0, 1, 2, 3 or 4.
If you believe that should never happen, just add:
default:
throw new InvalidOperationException("Invalid selected index " + workshopIndex);
Or if you just want to use some defaults, do something like:
default:
days = 1;
registration = 100;
break;
That's the first way you can end up with days and registration unassigned.
Next, there's the fact that you only go into the switch block at all if lbWorkshop.SelectedIndex != -1. Your else block is just:
else
{
MessageBox.Show("You didn't select a workshop.");
}
... so after that else block, you're going to continue. You probably want:
else
{
MessageBox.Show("You didn't select a workshop.");
return;
}
You've then got the same problem for locFees, in terms of both the switch statement and the else block.
One thing to learn from this: be grateful that the compiler spotted these for you. It's stopped you from running code which definitely had bugs in. That's always a good thing.

Categories