c# how to refer to current button - c#

I am trying to make a minesweeper game using Windows Application. I would like to use a switch inside a method.
The problem:
public void switcher()
{
switch (x)
{
case 0:
A1.BackgroundImage = Image.FromFile("empty.jpg"); // look at A1
break;
case 1:
A1.BackgroundImage = Image.FromFile("1.jpg");
break;
case 2:
A1.BackgroundImage = Image.FromFile("2.jpg");
break;
case 3:
A1.BackgroundImage = Image.FromFile("3.jpg");
break;
case 4:
A1.BackgroundImage = Image.FromFile("4.jpg");
break;
case 5:
A1.BackgroundImage = Image.FromFile("5.jpg");
break;
case 6:
A1.BackgroundImage = Image.FromFile("6.jpg");
break;
case 7:
A1.BackgroundImage = Image.FromFile("7.jpg");
break;
case 8:
A1.BackgroundImage = Image.FromFile("8.jpg");
break;
}
}
As you can see, each of them says "A1. ....." A1 is my first button's name, but there are many other buttons as well. Is there a way I can refer to the button's properties, such as background image, without having to use its name? It would make programming so much easier.
Here's a simplified part of the button, if it helps:
private void A1_Click(object sender, EventArgs e) // < - I want to refer to this without using A1 name.
{
x = bombcount[0, 0];
switcher();
}
edit: One of the answers worked. I don't know much about these things, but I'll try to learn more about them! Thank you!

You need to refactor this code altogether. Don't rely on private members such as x like that, use method parameters:
private void SetButtonImage(Button button, int number)
{
string imagePath;
if (number == 0)
{
imagePath = "empty.jpg";
}
else
{
imagePath = number + ".jpg";
}
button.BackgroundImage = Image.FromFile(imagePath);
}
Then call it like this:
private void Button_Click(object sender, EventArgs e)
{
var button = sender as Button;
int number = bombcount[0, 0];
SetButtonImage(button, number);
}
Now you can hook up all button click events to that single event handler, and you can remove the x member, and you can remove the switch altogether.

Get a reference in switcher to the button being clicked like this:
private void A1_Click(object sender, EventArgs e)
{
Button myB = (Button) sender;
x = bombcount[0,0];
switcher(myB);
}
private void switcher(Button button)
{
switch (x)
{
case 0:
button.BackgroundImage = Image.FromFile("empty.jpg"); // look at A1
break;
case 1:
button.BackgroundImage = Image.FromFile("1.jpg");
break;
case 2:
button.BackgroundImage = Image.FromFile("2.jpg");
break;
case 3:
button.BackgroundImage = Image.FromFile("3.jpg");
break;
case 4:
button.BackgroundImage = Image.FromFile("4.jpg");
break;
case 5:
button.BackgroundImage = Image.FromFile("5.jpg");
break;
case 6:
button.BackgroundImage = Image.FromFile("6.jpg");
break;
case 7:
button.BackgroundImage = Image.FromFile("7.jpg");
break;
case 8:
button.BackgroundImage = Image.FromFile("8.jpg");
break;
}
}

Related

How can l change PictureBox when user does not estimate a letter correct?

I'm trying to make a hangman game in C#. I've done most of the work. I use dynamic buttons as keyboard. My problem is, that when user clicks on a letter on keyboard that is not present in the word that user should estimate, picturebox should replaced with picturebox2, and if his estimation is again wrong, replace with picturebox3, go on until final picturebox. However, if user estimates the letter correctly, picturebox should not replaced. I tried to do this, but my code does not work, as when I click on a button, picturebox keep changing until the last picture even if my estimation is correct or not. where is my mistake?
Here is the part of my code:
void btn_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
btn.BackColor = Color.Aqua;
btn.ForeColor = Color.Red;
int a = 0;
// xy is the word that user should estimate
for (int i = 0; i < xy.Length; i++)
{
if (this.Controls.Find("txt" + i, true)[0].Text == btn.Text)
{
this.Controls.Find("txt" + i, true)[0].Text = btn.Text;
this.Controls.Find("txt" + i, true)[0].BackColor = Color.White;
}
else
{
a++;
switch(a)
{
case 1:
pictbx.Image = Image.FromFile("D:/Csharp_Pro/Games/Mine/hangman/hangman/skeleton1.png");
break;
case 2:
pictbx.Image = Image.FromFile("D:/Csharp_Pro/Games/Mine/hangman/hangman/skeleton2.png");
break;
case 3:
pictbx.Image = Image.FromFile("D:/Csharp_Pro/Games/Mine/hangman/hangman/skeleton3.png");
break;
case 4:
pictbx.Image = Image.FromFile("D:/Csharp_Pro/Games/Mine/hangman/hangman/skeleton4.png");
break;
case 5:
pictbx.Image = Image.FromFile("D:/Csharp_Pro/Games/Mine/hangman/hangman/skeleton5.png");
break;
default:
break;
}
}
}
}
First mistake is what Hans mentioned in comments: your variable must be a field of the class and not a local variable on the function, and must reset on each new game.
Second mistake: you check the letter the player clicked against every letter on the word, and for everytime it doesn't match, you add one to your error counter. You must add 1 only after you have finished checking all the letters in your word.
void btn_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
btn.BackColor = Color.Aqua;
btn.ForeColor = Color.Red;
bool found = false;
// xy is the word that user should estimate
for (int i = 0; i < xy.Length; i++)
{
if (this.Controls.Find("txt" + i, true)[0].Text == btn.Text)
{
this.Controls.Find("txt" + i, true)[0].Text = btn.Text;
this.Controls.Find("txt" + i, true)[0].BackColor = Color.White;
found = true;
}
}
if (!found)
{
a++;
switch(a)
{
case 1:
pictbx.Image = Image.FromFile("D:/Csharp_Pro/Games/Mine/hangman/hangman/skeleton1.png");
break;
case 2:
pictbx.Image = Image.FromFile("D:/Csharp_Pro/Games/Mine/hangman/hangman/skeleton2.png");
break;
case 3:
pictbx.Image = Image.FromFile("D:/Csharp_Pro/Games/Mine/hangman/hangman/skeleton3.png");
break;
case 4:
pictbx.Image = Image.FromFile("D:/Csharp_Pro/Games/Mine/hangman/hangman/skeleton4.png");
break;
case 5:
pictbx.Image = Image.FromFile("D:/Csharp_Pro/Games/Mine/hangman/hangman/skeleton5.png");
break;
default:
break;
}
}
}
It still has a lot of room for improvement, buy I decided to stop here so you can eventually find it out by yourself while you're learning.

Values not retained after postback during a method call

I am currently working on migration of a vb.net desktop application into a web application, in the desktop application the previous developer had declared all the variables once on the
form_load
stdate = VB6.Format(Now, "mmddyyyyhh")
current_month = CInt(Mid(stdate, 1, 2))
current_day = CInt(Mid(stdate, 3, 2))
current_year = CInt(Mid(stdate, 5, 4))
current_hour = CInt(Mid(stdate, 9, 2))
base_year = current_year
this_year = current_year
base_month = current_month
this_month = current_month
txtBaseyear.Text = CStr(base_year)
txtBaseMonth.Text = CStr(base_month)
swyearerror = 0
They were then able to use these variables anywhere in the code and it would retain the values.
my application
protected void Page_Load(object sender, EventArgs e)
{
DateTime now = DateTime.Now;
string format = "MMdyyyyhh";
string stdate = now.ToString(format);
Session["stdate"] = stdate;
int current_month = Convert.ToInt32(now.Month);
Session["currentmonth"] = current_month;
int current_day = Convert.ToInt32(now.Day);
Session["currentday"] = current_day;
int current_year = Convert.ToInt32(now.Year);
Session["currentyear"] = current_year;
int current_hour = Convert.ToInt32(now.Hour);
Session["currenthour"] = current_hour;
int base_year = (int)(Session["currentyear"]);
int this_year = (int)(Session["currentyear"]);
int base_month = (int)(Session["currentmonth"]);
int this_month = (int)(Session["currentmonth"]);
TxtBase.Text = Convert.ToString(base_year);
TxtBase1.Text = Convert.ToString(base_month);
}
Now each time there is a post-back when the text is changed the values are lost and set to zero so I tried storing it in a session but that still doesn't work.
Let me give you a visual of my situation.
1) on the first load everything loads fine.
2) then the users enters an item and hits enter
protected void TxtItem_TextChanged(object sender, EventArgs e)
{
Calc_Rotation();
Calc_Best_Before();
}
now...
public void Calc_Rotation()
{
switch (current_month) becomes 0 suppose to be 4
{
case 1:
rotation_month = "A";
break;
case 2:
rotation_month = "B";
break;
case 3:
rotation_month = "G";
break;
case 4:
rotation_month = "J";
break;
case 5:
rotation_month = "K";
break;
case 6:
rotation_month = "L";
break;
case 7:
rotation_month = "N";
break;
case 8:
rotation_month = "P";
break;
case 9:
rotation_month = "S";
break;
case 10:
rotation_month = "W";
break;
case 11:
rotation_month = "Y";
break;
case 12:
rotation_month = "Z";
break;
}
switch (current_hour) becomes 0 suppose to be the current hour
{
case 0:
case 1:
rotation_batch = 2;
break;
case 2:
case 3:
rotation_batch = 4;
break;
case 4:
case 5:
rotation_batch = 6;
break;
case 6:
case 7:
rotation_batch = 8;
break;
case 8:
case 9:
rotation_batch = 10;
break;
case 10:
case 11:
rotation_batch = 12;
break;
case 12:
case 13:
rotation_batch = 14;
break;
case 14:
case 15:
rotation_batch = 16;
break;
case 16:
case 17:
rotation_batch = 18;
break;
case 18:
case 19:
rotation_batch = 20;
break;
case 20:
case 21:
rotation_batch = 22;
break;
case 22:
case 23:
rotation_batch = 24;
break;
}
}
same goes for the Calc_Best_Before
after I tried the postback solution I am still getting 0 values.
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
return;
DateTime now = DateTime.Now;
string format = "MMdyyyyhh";
string stdate = now.ToString(format);
Session["stdate"] = stdate;
int current_month = Convert.ToInt32(now.Month);
Session["currentmonth"] = current_month;
int current_day = Convert.ToInt32(now.Day);
Session["currentday"] = current_day;
int current_year = Convert.ToInt32(now.Year);
Session["currentyear"] = current_year;
int current_hour = Convert.ToInt32(now.Hour);
Session["currenthour"] = current_hour;
int base_year = (int)(Session["currentyear"]);
int this_year = (int)(Session["currentyear"]);
int base_month = (int)(Session["currentmonth"]);
int this_month = (int)(Session["currentmonth"]);
TxtBase.Text = Convert.ToString(base_year);
TxtBase1.Text = Convert.ToString(base_month);
}
Put your code inside the below code. If the web page loads for the first time IsPostBack property is 'false' and code inside the if condition will be executed.
if the page loads after a post back IsPostBack turns to 'true' which cause program execution to escape the if condition.
if (!IsPostBack)
{
}
In case you are using Session to store the values, you need to ensure that you are checking the IsPostBack Property. Otherwise, everytime the page postback occurs, you are initializing the values again and thus you loose the state.
Page.IsPostBack property basically signifies whether the Page is accessing the server for the first time or not.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DateTime now = DateTime.Now;
string format = "MMdyyyyhh";
string stdate = now.ToString(format);
Session["stdate"] = stdate;
int current_month = Convert.ToInt32(now.Month);
Session["currentmonth"] = current_month;
int current_day = Convert.ToInt32(now.Day);
Session["currentday"] = current_day;
int current_year = Convert.ToInt32(now.Year);
Session["currentyear"] = current_year;
int current_hour = Convert.ToInt32(now.Hour);
Session["currenthour"] = current_hour;
int base_year = (int)(Session["currentyear"]);
int this_year = (int)(Session["currentyear"]);
int base_month = (int)(Session["currentmonth"]);
int this_month = (int)(Session["currentmonth"]);
TxtBase.Text = Convert.ToString(base_year);
TxtBase1.Text = Convert.ToString(base_month);
}
}
UPDATE 1:
#CodeMan: You need to use the Session to read the value for the current month in the function Calc_Rotation. You are trying to read the value from the variable current_month which is an int and would default to zero.
I would suggest you to use a Property to wrap up the Session Variable and then use the property in the code. Below, i have created a wrapper property CurrentMonth which encapsulates the Read and write operations on Session in the webpage, declared at class scope. Simmilary you can create wrapper properties for other variables as well. After creating the properties, you need to read the property value in the Calc_Rotation function.
private int CurrentMonth {
get {
var monthfromSession = HttpContext.Current.Session["ClassNameSpace.CurrentMonth"];
return monthfromSession!= null ? (int)monthfromSession : 0;
}
set {
HttpContext.Current.Session["ClassNameSpace.CurrentMonth"] = value;
}
}
public void Calc_Rotation()
{
switch (this.CurrentMonth) // it should have correct month value now.
{
case 1:
rotation_month = "A";
break;
case 2:
rotation_month = "B";
break;
case 3:
....
}
}

Switch statement object to int problems

I am trying to use the selectedItem command to see what has been selected in the list box and then use the switch to set the activityLevel variable depending on what has been selected. I then need to be able to multiply that variable by the BMR variable that is set as a double. Then the result is displayed in a label.
string activityLevel = lstActivityLevel.SelectedItem.ToString();
switch (activityLevel)
{
case 1:
activityLevel = Convert.ToInt32(ACTIVTY_LEVEL2);
break;
case 2:
activityLevel = Convert.ToInt32(ACTIVTY_LEVEL3);
break;
case 3:
activityLevel = Convert.ToInt32(ACTIVTY_LEVEL4);
break;
case 4:
activityLevel = Convert.ToInt32(ACTIVTY_LEVEL5);
break;
}
//Display BMR in label
lblBMRResult.Text = (BMR*activityLevel).ToString();
You can use SelectedIndex, then each item of lstActivityLevel set to number from 0 to 4:
double activityLevel = 0;
switch (lstActivityLevel.SelectedIndex)
{
case 0:
activityLevel = ACTIVTY_LEVEL1;
break;
case 1:
activityLevel = ACTIVTY_LEVEL2;
break;
case 2:
activityLevel = ACTIVTY_LEVEL3;
break;
case 3:
activityLevel = ACTIVTY_LEVEL4;
break;
case 4:
activityLevel = ACTIVTY_LEVEL5;
break;
}
lblBMRResult.Text = (BMR * activityLevel).ToString();
You convert SelectedItem value to string. And value 1 (int) is not the same as "1" (string)... So, you have to change your switch statement to:
switch (activityLevel)
{
case "1":
blah, blah...
break;
}
and so on..
Or do not call ToString() on SelectedItem.
Or you can use SelectedIndex instead of SelectedItem..

Text added to combo box is highlighted

I have a method that appends or inserts characters to the text of either a combo box or textbox depending on what was last focused on. I am using buttons to pass in the character as a parameter, Using a keyboard or sendkeys is not an option. When my method appends or inserts characters into a textbox the result is as expected however when the same method is applied to a combobox the text of the combobox is highlighted. Obviously this is not the functionality im looking for and I believe this is stopping the autocomplete mode from working correctly.
Why is the combobox behaving differently than the textbox?
The code:
private void createText(string lowerCaseChar, string upperCaseChar)
{
Control FocusedTextComboBox;
switch (lastTextComboBoxFocused)
{
case 54:
FocusedTextComboBox = SearchTextBox;
break;
case 4:
FocusedTextComboBox = VendorComboBox;
break;
case 6:
FocusedTextComboBox = SectionComboBox;
break;
case 5:
FocusedTextComboBox = DeptComboBox;
break;
default:
FocusedTextComboBox = SearchTextBox;
break;
}
if (FocusedTextComboBox is TextBox)
{
TextBox FocusedTextBox = (TextBox)FocusedTextComboBox;
int SelectionStartNumber = FocusedTextBox.SelectionStart;
switch (shift)
{
case true:
FocusedTextBox.Text = FocusedTextBox.Text.Insert(FocusedTextBox.SelectionStart, upperCaseChar);
break;
case false:
FocusedTextComboBox.Text = FocusedTextComboBox.Text.Insert(FocusedTextBox.SelectionStart, lowerCaseChar);
break;
}
FocusedTextBox.SelectionStart = SelectionStartNumber + 1;
FocusedTextBox.Focus();
}
else
{
ComboBox FocusedComboBox = (ComboBox)FocusedTextComboBox;
if (FocusedComboBox.SelectionStart == 0 && FocusedComboBox.Text != "")
{
switch (shift)
{
case true:
FocusedComboBox.Text += upperCaseChar;
break;
case false:
FocusedComboBox.Text += lowerCaseChar;
break;
}
}
else
{
int SelectionStartNumber = FocusedComboBox.SelectionStart;
switch (shift)
{
case true:
FocusedComboBox.Text = FocusedComboBox.Text.Insert(FocusedComboBox.SelectionStart, upperCaseChar);
break;
case false:
FocusedTextComboBox.Text = FocusedTextComboBox.Text.Insert(FocusedComboBox.SelectionStart, lowerCaseChar);
break;
}
FocusedComboBox.SelectionStart = SelectionStartNumber + 1;
}
FocusedComboBox.Focus();
}
}
I think setting focus back to the combobox is highlighting the text, move FousedCombox.Focus() to before assigning text to combobox.

Switch case statement

I am trying to create an application in C# that converts numbers in a text box to roman numerals in a label control and need to use a case statement. However one of my variable Roman gets the error message: Use of unassigned local variable 'Roman'.
Here is my code:
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 Roman_Numeral_Converter
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnCalc_Click(object sender, EventArgs e)
{
int Number=int.Parse(txtNum.Text); // To hold Number
string Roman; // To hold Roman Numeral
if (Number>=1 && Number <=10)
{
switch (Roman)
{
case "Number==1":
lblRoman.Text = "I";
break;
case "Number==2":
lblRoman.Text = "II";
break;
case "Number==3":
lblRoman.Text = "III";
break;
case "Number==4":
lblRoman.Text = "IV";
break;
case "Number==5":
lblRoman.Text = "V";
break;
case "Number==6":
lblRoman.Text = "VI";
break;
case "Number==7":
lblRoman.Text = "VII";
break;
case "Number==8":
lblRoman.Text = "VIII";
break;
case "Number==9":
lblRoman.Text = "IX";
break;
case "Number==10":
lblRoman.Text = "X";
break;
}
}
else
{
MessageBox.Show("Error: Invalid Input");
}
}
private void btnExit_Click(object sender, EventArgs e)
{
// Close the form.
this.Close();
}
private void btnClear_Click(object sender, EventArgs e)
{
txtNum.Text = "";
lblRoman.Text = "";
}
}
}
Your structure is a little off.
private void btnCalc_Click(object sender, EventArgs e)
{
var Number = int.Parse(txtNum.Text); // To hold Number
switch (Number)
{
case 1:
lblRoman.Text = "I";
break;
case 2:
lblRoman.Text = "II";
break;
case 3:
lblRoman.Text = "III";
break;
case 4:
lblRoman.Text = "IV";
break;
case 5:
lblRoman.Text = "V";
break;
case 6:
lblRoman.Text = "VI";
break;
case 7:
lblRoman.Text = "VII";
break;
case 8:
lblRoman.Text = "VIII";
break;
case 9:
lblRoman.Text = "IX";
break;
case 10:
lblRoman.Text = "X";
break;
default:
MessageBox.Show("Error: Invalid Input");
break;
}
}
You're using the lblRoman to hold your result, thus your Roman variable is unnecessary. Additionally, since you're interrogating every possible valid number in your switch, you can just use the default to replace your if/else structure.
I'm assuming you're doing this as an academic exercise. That being said, I would be remiss not to point to you Mosè Bottacini's solution to this problem.
This is because Roman variable is really unassigned. You should assign it before you enter the statement
try this,
when your number value like 1 so roman number is I.
private void btnCalc_Click(object sender, EventArgs e)
{
int Number = int.Parse(txtNum.Text); // To hold Number
string Roman; // To hold Roman Numeral
if (Number >= 1 && Number <= 10)
{
switch (Number)
{
case 1:
lblRoman.Text = "I";
break;
case 2:
lblRoman.Text = "II";
break;
case 3:
lblRoman.Text = "III";
break;
case 4:
lblRoman.Text = "IV";
break;
case 5:
lblRoman.Text = "V";
break;
case 6:
lblRoman.Text = "VI";
break;
case 7:
lblRoman.Text = "VII";
break;
case 8:
lblRoman.Text = "VIII";
break;
case 9:
lblRoman.Text = "IX";
break;
case 10:
lblRoman.Text = "X";
break;
}
}
else
{
MessageBox.Show("Error: Invalid Input");
}
}
Instead of switch, You can do other way using Linq which is even better.
int Number=int.Parse(txtNum.Text);
var romanList = new List<string> {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"};
if (Number >= 1 && Number <= 10)
lblRoman.Text = romanList.Select((r, i) => new { Roman = r, Index = i+1}).FirstOrDefault(x=> x.Index == Number).Roman;
you can replace your switch statement this way. and of course you need to assign a variable before using it.
public string GetNum(string val)
{
string res = ""; // Assign it an empty string.
var numToRom = new Dictionary<string, string>
{
{"1","I"},
{"2","II"}
//so on
};
numToRom.TryGetValue(val, out res);
return res;
}

Categories

Resources