I have made 4 radio buttons and set their tag to wood, diamond, clay, and brick. I want to find the checked one and set a Bitmap property based on the selected radio button. Disregard the fact that it should be split into more methods, that will be done when i refactor. The properties cellBgImage in Map and Cell are null.
void setCellBgImage()
{
string cellBgImage = "";
foreach (Control c in myMap.myForm.Controls)
{
if (c is RadioButton)
{
RadioButton radio = c as RadioButton;
if (radio.Checked)
{
cellBgImage = radio.Tag.ToString();
}
}
}
switch (cellBgImage)
{
case "wood":
myMap.cellBgImage = (Bitmap)Bitmap.FromFile("Images/wood.png");
break;
case "diamond":
myMap.cellBgImage = (Bitmap)Bitmap.FromFile("Images/diamond.png");
break;
case "clay":
myMap.cellBgImage = (Bitmap)Bitmap.FromFile("Images/clay.png");
break;
case "brick":
myMap.cellBgImage = (Bitmap)Bitmap.FromFile("Images/brick.png");
break;
}
foreach (Cell cell in myMap.myCells)
{
cell.myBgImage = myMap.cellBgImage;
}
}
Add a default case to the switch so when none of them are checked you still get a value in myMap.cellBgImage.
default:
myMap.cellBgImage = (Bitmap)Bitmap.FromFile("Images/brick.png");
break;
As you write at the comments your RB are in panel1. so you should do the Foreach like this:
foreach (Control c in this.panel1.Controls)
Related
I'm working on a desktop application in which I want to allow the user to control it's functionalities via Keyboard, also allow him to change the default controllers to a custom controllers according to his point of view.
My question is, what is the best approach to tackle this problem and provide an appropriate solution to this problem?
You can use a Dictionary to bound each key to an action
My approach here is to use a Dictionary where the Key is actual Keybord Keys and value is an int? representing one of your function that can be bound to a custom input.
Dictionnary<Keys, int?> shortcutDictionnary = new Dictionary<Keys, int?>();
// Add a new Keys
shortcutDictionary.Add(Keys.A, 1);
// Change a Keys value (change shortcut bounded to it)
shortcutDictionary[Keys.A] = 4;
To match those int? with these functions you only have to use a switch :
int? num = null;
if (this.shortcutDictionary.TryGetValue(keyPressed, out num))
{
switch (num)
{
case 1:
attack();
break;
case 2:
defend();
break;
case 3:
hide();
break;
case 4:
dance();
break;
default:
Console.WriteLine("Key not bounded");
break;
}
}
I also in my code below use an enum instead of direct use of Keys for my Dictionary. This way, I can choose which Keys can be bounded and which one can't.
My code made from a Winform app, as an exemple I only used 4 Keys (A,B,C,D) which can be bound and one to easily change bound (L), but I'm sure you can figure out how to change bound easily with any other method. Also as I'm working with a WindowsForm, I had to set KeyPreview = true.
Here's my code :
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace Project
{
public enum UsableKeys
{
A = Keys.A,
B = Keys.B,
C = Keys.C,
D = Keys.D,
}
public partial class Form1 : Form
{
Dictionary<UsableKeys, int?> shortcutDictionary = new Dictionary<UsableKeys, int?>();
public Form1()
{
InitializeComponent();
foreach (UsableKeys key in Enum.GetValues(typeof(UsableKeys)))
{
// You may add default shortcut here
this.shortcutDictionary.Add(key, null);
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
UsableKeys keyPressed = (UsableKeys)e.KeyCode;
if (this.shortcutDictionary.ContainsKey(keyPressed))
{
executeAction(keyPressed);
e.Handled = true;
e.SuppressKeyPress = true;
}
else if (e.KeyCode == Keys.L)
{
switch (this.shortcutDictionary[UsableKeys.A])
{
case 1:
this.shortcutDictionary[UsableKeys.A] = 4;
this.shortcutDictionary[UsableKeys.B] = 3;
this.shortcutDictionary[UsableKeys.C] = 2;
this.shortcutDictionary[UsableKeys.D] = 1;
break;
case null:
this.shortcutDictionary[UsableKeys.A] = 1;
this.shortcutDictionary[UsableKeys.B] = 2;
this.shortcutDictionary[UsableKeys.C] = 3;
this.shortcutDictionary[UsableKeys.D] = 4;
break;
case 4:
this.shortcutDictionary[UsableKeys.A] = null;
this.shortcutDictionary[UsableKeys.B] = null;
this.shortcutDictionary[UsableKeys.C] = null;
this.shortcutDictionary[UsableKeys.D] = null;
break;
}
e.Handled = true;
e.SuppressKeyPress = true;
}
}
private void executeAction(UsableKeys keyPressed)
{
int? num = null;
if (this.shortcutDictionary.TryGetValue(keyPressed, out num))
{
switch (num)
{
case 1:
attack();
break;
case 2:
defend();
break;
case 3:
hide();
break;
case 4:
dance();
break;
default:
Console.WriteLine("Key not bounded");
break;
}
}
}
private void attack()
{
Console.WriteLine("Player swing his word");
}
private void defend()
{
Console.WriteLine("Player raise his shield");
}
private void hide()
{
Console.WriteLine("Player sneak around");
}
private void dance()
{
Console.WriteLine("Player start to dance");
}
}
}
With this code, output will be like :
// Press A, B, C or D
"Key not bounded"
// Press L
// Press A
"Player swing his word"
// Press B
"Player raise his shield"
// Press C
"Player sneak around"
// Press D
"Player start to dance"
// Press L
// Press A
"Player start to dance"
// Press B
"Player sneak around"
// Press C
"Player raise his shield"
// Press D
"Player swing his sword"
// Press L
// Press A, B, C or D
"Key not bounded"
Exemple to change key binding in run time :
// Create a new Dictionary for shortcuts
Dictionary<UsableKeys, int?> shortcutDictionary = new Dictionary<UsableKeys, int?>();
// Add a pair key/value that bind A to attack()
shortcutDictionary.Add(UsableKey.A, 1);
// Add a pair Key/value that bind B to defend()
shortcutDictionary.Add(UsableKey.B, 2);
// Now, if you press A, attack() will be called
shortcutDictionary[UsableKey.A] = 2;
// Now if you press A or B, defend() will be called
shortcutDictionary[UsableKey.B] = null;
// Now B isn't bind to any function, so only A is binded to defend();
With this method, you can't bind multiple functions to one Keys while you can bind multiple Keys to one function (If you want to inverse that, just swap key/value of Dictionary and adjust the code to match this).
I don't know if it's the optimal way to do this, but it isn't spaghetti code and it works well.
I have radio buttons, around 200, whose ID are KP1, KP2, KP3... KP200. I would like to run a for loop to check if they are checked or not.
I get a crash at the line no 9:
RbId = CtrlId;
I would like to extract the Radio Button Ctrl from the string similar to how it's done using javascript ie.,
document.getElementById("<%=ID%>").
Please advise.
Code:
int i;
RadioButton RbId = null;
string CtrlId = null;
char[] KPList = new char[200];
for (i = 1; i <= 200; i++)
{
CtrlId = "KP"+i.ToString();
RbId = CtrlId;
if(RbId.Checked)
{
KPList[i] = (char)j;
break;
}
}
You can use FindControl() method in for it:
Control ctrl = this.FindControl(CtrlId);
if (ctl is RadioButton)
{
RadioButton rdBtn = ctrl as RadioButton;
// now do whatever here
if(rdBtn.Checked)
{
}
}
Try this:
foreach (RadioButton rdbtn in myDiv.Controls.OfType<RadioButton>())//Assume the RadioButtons are inside a div tag called myDiv
{
if(rdbtn.Checked)
{
....
}
}
It would be even better like this:
foreach (RadioButton rdbtn in myDiv.Controls.OfType<RadioButton>().Where(rdbtn => rdbtn.Checked))
{
}
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.
Several places in my program, the RadioButton matching the selected item has to be checked, and I have a lot of if statements like so:
DataRowView TempRow = (DataRowView)ScheduleDataGrid.SelectedItem;
if (Convert.ToString(TempRow["Bio"]) == "Bio1")
{
BioRB1.IsChecked = true;
}
if (Convert.ToString(TempRow["Bio"]) == "Bio2")
{
BioRB2.IsChecked = true;
}
if (Convert.ToString(TempRow["Bio"]) == "Bio3")
and so on... I want to replace all this with something short and smart.
I tried using the number of the bio to relate to the button like so:
string bioselected = Convert.ToString(TempRow["Bio"]);
int i = Convert.ToInt16(bioselected.Substring(bioselected.Length - 1, 1));
BioRB[i].IsChecked = true;
but doing a BioRB[i] doesn't work, it ignores the [i] and says BioRB does not exist. Any other suggestions?
BioRB[i] is not doing anything like what you think it's doing. All variable references (controls included) have to be well-defined at compile time - you can't refer to a control's name by building a string that matches the name.**
Try creating a list of your radio buttons. Then you can index into the list:
List<RadioButton> radioButtons = new List<RadioButton>()
{
BioRB1,
BioRB2
};
string bioselected = Convert.ToString(TempRow["Bio"]);
int i = Convert.ToInt16(bioselected.Substring(bioselected.Length - 1, 1));
radioButtons[i].IsChecked = true;
** Technically you can do this via reflection, but it's far more complex than what you've tried.
Maybe this will look better:
string caseSwitch = Convert.ToString(TempRow["Bio"]);
switch (caseSwitch)
{
case "Bio1":
BioRB1.IsChecked = true;
break;
case "Bio2":
BioRB2.IsChecked = true;
break;
case "Bio3":
BioRB3.IsChecked = true;
break;
default:
Console.WriteLine("Default case...is optional");
break;
}
Also, try doing what Alybaba726 said and use CellContentClick or something like this:
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
DataGridView dgv = (DataGridView)sender;
if(e.ColumnIndex == dgv.Columns["Bio"].Index)
{
string bioSelected = dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
switch (bioSelected)
{
case "Bio1":
BioRB1.IsChecked = true;
break;
case "Bio2":
BioRB2.IsChecked = true;
break;
case "Bio3":
BioRB3.IsChecked = true;
break;
default:
Console.WriteLine("Default case...this is optional");
break;
}
}
}
I've made a switch-case where I use the up arrow key, down arrow key and enter key. However I can't think of how to put code into my enter case in which I can choose an option.
public static void entries()
{
keyPressed = Console.ReadKey(true);
switch (keyPressed.Key)
{
case ConsoleKey.DownArrow:
if (keyPressed.Key.ToString() == "DownArrow")// selects the curitem when the down arrow key is pressed
{
curItem++;
if (curItem > menuItems.Length - 1) curItem = 0;
}
break;
case ConsoleKey.UpArrow:
if (keyPressed.Key.ToString() == "UpArrow")// selects the curitem when the up arrow key is pressed
{
curItem--;
if (curItem < 0) curItem = Convert.ToInt16(menuItems.Length - 1);
}
break;
case ConsoleKey.Enter:
if (keyPressed.Key.ToString() == "Enter")// when enter is pressed it will go to one of the choices
{
}
break;
default:
break;
}
}
Your idea about nesting if statements is correct, or having another switch. I would probably re-factor this into another function though:
case ConsoleKey.Enter:
chooseOption(curItem);
break;
...
void chooseOption(int item)
{
switch(item)
{
case 1:
//Do item 1
break;
case 2:
//Do item 2
break;
case 3:
//Do item 3
break;
}
}
Based on your comment. here is how you can display the current item inside the menuItems array. I'm assuming menuItems holds some strings or ints or something that can be easily written to the console.
case ConsoleKey.Enter:
// when enter is pressed it will go to one of the choices
Console.Clear();
Console.WriteLine(menuItems[curItem]);
break;