Relatively new to C#. I have to make a Tic Tac Toe. I am thinking of using only one method to change my button properties.
This is what I imagine.
int count = 0;
private void button1_Click(object sender, EventArgs e)
{
ChangeButton(count);
}
public int ChangeButton(int i)
{
if(count % 2 == 0)
{
// button.text = x
// i want to be able to change the text of whichever button is clicked
}
else
{
// button.text = o
}
// button.enable = false
// I want to disable whichever button is clicked
i++;
return i;
}
I don't know should I do the // parts. Hope you can help me. Thanks!
If you have several buttons all calling the same click event, you can identify the button from the sender parameter:
Button btn = sender as Button;
Then you can change the text for that button:
btn.Text = count++ % 2 == 0 ? "x" : "o";
All in your click event:
int count = 0;
private void button1_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
btn.Text = count++ % 2 == 0 ? "x" : "o";
btn.Enabled = false;
}
Related
It goes like this, I have a numericUpDown which has a max value of 4. I want to make it so if the value is 1 only one button appears, if value is 2, two buttons appears, etc. How can I manage to do this in code ? I am using a timer and on every tick it checks if the value of the numericUpDown changes and if its changed it adds buttons, but how can I do the opposite thing, if value decreases, remove buttons? For example if I have the value of 4 and I already have 4 buttons appeared if I decrease with ONE, only one button should go away. How can I do this ?
private void timer1_Tick(object sender, EventArgs e)
{
if (numericUpDown1.Value == 1)
{
metroComboBox3.Show();
}
else if (numericUpDown1.Value == 2)
{
metroComboBox4.Show();
}
}
Simply do a double click on you numericUpDown in design, you dont need a timer.
You will get private void numericUpDown1_ValueChanged
Afther that your code should look like this:
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
if (numericUpDown1.Value == 1)
{
metroComboBox3.Show();
}
else if (numericUpDown1.Value == 2)
{
metroComboBox4.Show();
}
}
If you have to do it with a timer then this is the way to go:
private void timer1_Tick(object sender, EventArgs e)
{
var buttons = new [] { button1, button2, button3, button4, };
for (var i = 0; i < buttons.Length; i++)
{
buttons[i].Visible = numericUpDown1.Value - 1 >= i
}
}
But I would use the numericUpDown1.ValueChanged event and do this:
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
var buttons = new [] { button1, button2, button3, button4, };
for (var i = 0; i < buttons.Length; i++)
{
buttons[i].Visible = numericUpDown1.Value - 1 >= i
}
}
I am writing a simple calculator script for my C# programming class. It will of course have buttons 0-9 that will update the output textbox to add the number of whatever button is clicked. My problem right now that is I would rather not have to have 10 different click events in my script. I would rather have a loop that cycles through the buttons that will add the same click event to each one and then decide what number to add to the output based on the button.
So right now, I have a click event for the "1" button which is this...
private void btnNum1_Click(object sender, EventArgs e)
{
txtOutput.Text = Convert.ToString(txtOutput.Text + "1");
}
This works fine, but, again, I would rather not have to do this 10 times. How can I create a loop that prevents this?
The button names are btnNum1, btnNum2, btnNum3, etc.
Assuming the button text is just "1", "2" etc you could do this:
private void btnNum_Click(object sender, EventArgs e)
{
var button = sender as Button
txtOutput.Text += button.Content.ToString();
}
Then just apply this event to all the buttons.
Also note you don't need Convert.ToString() as what you are trying to convert is already a string. Using += also cleans up your code a bit.
You could do this to wire-up all of the events in one go:
for (var n = 0; n <= 9; n++)
{
var btn =
this
.Controls
.Find("btnNum" + n.ToString(), false)
.Cast<Button>()
.First();
var digit = n;
btn.Click += (s, e) =>
{
txtOutput.Text = digit.ToString();
};
}
You could enumerate the children controls of your Form/Control, look the type of controls which are type of Button and the name StartWith 'btnNum', with each of these buttons, add a Click event address to btnNum_Click().
Say if all your buttons are contained in a Panel named 'pnlButtons', you could loop all the children like this.
foreach (var control in pnlButtons.Controls)
{
if(control.GetType() == typeof(Button))
{
var button = control as Button;
if (button .Name.StartWith('btnNum'))
{
button.Click += btnNum_Click;
}
}
}
You can use the "Tag" property of the Button control and make an array of Buttons to subscribe to the same event. See sample below:
void InitializeButtons()
{
Button btnNum1 = new Button();
btnNum1.Text = "1";
btnNum1.Tag = 1;
//Button 2..8 goes here
Button btnNum9 = new Button();
btnNum9.Text = "9";
btnNum9.Tag = 9;
Button[] buttons = new Button[]{
btnNum1, btnNum2, btnNum3, btnNum4, btnNum5, btnNum6, btnNum7, btnNum8, btnNum9
};
for (int i = 0; i < buttons.Length; i++)
{
buttons[i].Click += Button_Click;
}
}
void Button_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
int value = (int)button.Tag;
//Do something with value
}
Assuming WinForms, you can recursively search for buttons that start with "btnNum" and wire them up to a common handler like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Load += Form1_Load;
}
void Form1_Load(object sender, EventArgs e)
{
FindButtons(this);
}
private void FindButtons(Control ctl)
{
foreach(Control ctrl in ctl.Controls)
{
if (ctrl.Name.StartsWith("btnNum") && (ctrl is Button))
{
Button btn = (Button)ctrl;
btn.Click += btn_Click;
}
else if(ctrl.HasChildren)
{
FindButtons(ctrl);
}
}
}
private void btn_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
txtOutput.Text = Convert.ToString(txtOutput.Text + btn.Text);
}
}
This is the code.
In Form1 Load event:
private void Form1_Load(object sender, EventArgs e)
{
if (listBox1.Items != null && listBox1.Items.Count > 0)
{
listBox1.Select();
label4.Text = listBox1.SelectedItem.ToString();
string startTag = "Url: ";
string endTag = " ---";
int startTagWidth = startTag.Length;
int endTagWidth = endTag.Length;
int index = 0;
index = label4.Text.IndexOf(startTag, index);
int start = index + startTagWidth;
index = label4.Text.IndexOf(endTag, start + 1);
string g = label4.Text.Substring(start, index - start);
label4.Text = g;
mainUrl = g;
listboxContextMenu = new ContextMenuStrip();
listboxContextMenu.Opening += new CancelEventHandler(listboxContextMenu_Opening);
}
}
Then the listBox mouseDown event:
private void listBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
int index = listBox1.IndexFromPoint(e.Location);
{
if (index == listBox1.SelectedIndex)
{
listboxContextMenu.Show();
}
}
}
}
Then the Opening event:
private void listboxContextMenu_Opening(object sender, CancelEventArgs e)
{
//clear the menu and add custom items
listboxContextMenu.Items.Clear();
listboxContextMenu.Items.Add(string.Format("Edit - {0}", listBox1.SelectedItem.ToString()));
}
What it does is that when I click on a specific item in the listBox on the mouse right buttin it's showing the contextMenu.
The problem is that the contextMenu show up all the time on the screen on the top left corner not the Form but the screen top left corner.
Second problem is that the contect menu show up only on the second time I click the selected item.
When im running my program the first item in the listBox is already selected and yet the contect menu show up only when I click twice on the item. After that I click once each time but first time when running my program I need to click twice on my right button click.
How can I fix these two problems ?
Use the MouseUp Event instead of MouseDown Event
private void listBox1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
int index = listBox1.IndexFromPoint(e.Location);
if (index == - 1) return;
listBox1.SelectedIndex = index;
listboxContextMenu.Show(listBox1, listBox1.PointToClient(System.Windows.Forms.Cursor.Position));
}
}
When I run my program with a listbox everything works after selecting the items and pressing enter, but when I press the clear button and I select the items again and press enter nothing happens. I've tried the following for the clear button and they clear my label text and the selected listbox but I can no longer produce another output when I try pressing enter button again after selecting the items.
public partial class frmLabSix : Form
{
public string strCakes;
public int cakeCost;
public frmLabSix()
{
InitializeComponent();
}
private void lstCakes_SelectedIndexChanged(object sender, EventArgs e)
{
for (int index = 0; index < lstCakes.SelectedItems.Count; index++)
{
strCakes += Environment.NewLine + lstCakes.SelectedItems[index].ToString();
if (lstCakes.SelectedIndices[index] == 0) cakeCost += 18;
if (lstCakes.SelectedIndices[index] == 1) cakeCost += 25;
if (lstCakes.SelectedIndices[index] == 2) cakeCost += 40;
if (lstCakes.SelectedIndices[index] == 3) cakeCost += 30;
}
}
private void lblOrdered_Click(object sender, EventArgs e)
{
}
private void btnEnter_Click(object sender, EventArgs e)
{
double tax = 1.13;
lblOrdered.Text = "You have ordered: " + strCakes + '\n' + "Total Cost: " + (tax * cakeCost).ToString("C");
lblOrdered.Visible = true;
}
private void btnClear_Click(object sender, EventArgs e)
{
lstCakes.SelectedItems.Clear();
lblOrdered.Visible = false;
}
private void btnExit_Click(object sender, EventArgs e)
{
this.Close();
}
}
Can someone tell me why this is?
This line of code hides your label.
lblOrdered.Visible = false;
You make your label invisible on clear button click. Do you reset its visibility after?
I don't know, what happens in other part of your code, but it should probably be like this:
// if the label is not visible, the next line won't make it visible implicitly
lblOrdered.Text = ...
//you should set label's visibility explicitly
if (!lblOrdered.Visible)
lblOrdered.Visible = true;
Setting label's text doesn't make it visible. If you hide it with your own code, you should make label visible explicitly as well.
I have created a number of silverlight buttons thus:-
string b = "Button";
for (int i = 0; i < 10; i++)
{
Button btn = new Button();
btn.Name = b+i.ToString();
btn.FontSize += 2;
btn.Content = "Click Me " ;
btn.Click += new RoutedEventHandler(btn_Click);
stack.Children.Add(btn);
}
LayoutRoot.Children.Add(stack);
In the button click event I want to get the name of the button that was pressed. I had hoped that
string snd = sender.ToString(); would yield the information but all it gives is System.Windows.Controls.Button. Can anyone please help. Thanks.
You need to cast sender to a button.
public void btn_Click(object sender, EventArgs e)
{
var btn = (Button)sender;
Console.WriteLine(btn.Name);
}
public void btn_Click(object sender, EventArgs e)
{
var b = sender as Button;
if (b != null)
{
var name = b.Name;
// do something with name
}
}
Try this:
(sender as Button).Name
source