10x10 grid of 100 buttons: hiding a button on click (C#) - c#

I have a 10x10 grid of 100 buttons, I want to hide a button when it is clicked.
Is there a way to apply this to all buttons?? i.e. When any of the button is clicked then that button is hidden. I use a table layout to arrange the 100 buttons in C#.
also im adding it to table layout so kindly tell me how to add these buttons to that 10x10 table grid..here how will the button objects be named and how to add individual events all performing the action to itself(that is hide itself when clicked)

Create 100 buttons
foreach (int i in Enumerable.Range(0, 10))
{
foreach (int j in Enumerable.Range(0, 10))
{
Button b = new Button();
b.Size = new System.Drawing.Size(20, 20);
b.Location = new Point(i * 20, j * 20);
b.Click += new EventHandler(anyButton_Click); // <-- all wired to the same handler
this.Controls.Add(b);
}
}
and connect them all to the same event handler
void anyButton_Click(object sender, EventArgs e)
{
var button = (sender as Button);
if (button != null)
{
button.Visible = false;
}
}
in the eventhandler you cast sender to Button and that is the specific button that was pressed.

Since you are using tablelayoutpanel, you don't need to calculate positions for the buttons, the control is doing it for you. You can also set the buttons dock property to be fill, so you don't need to setup size of the buttons. All you'll have to do is to setup the properties of the tableLayoutPanle
So..
Button b;
foreach (int i in Enumerable.Range(0, 100))
{
b = new Button();
//b.Size = new System.Drawing.Size(20, 20);
b.Dock = DockStyle.Fill
b.Click += new EventHandler(anyButton_Click); // <-- all wired to the same handler
tableLayoutPanel.Controls.Add(b);
}

Related

Don't know how to get index from button list C# winForms

I am writing a program code for creating graphs from graph theory.
Clicking on a grid generates a graph node with the corresponding index. Buttons are generated on the right. I want the nodes to be connected by an edge when the button is clicked. For example, when you click on the button on line 1 and column 2, an edge will be drawn connecting circles 1 and 2.
enter image description here
Button generation code
List<Button> btnList = new List<Button>();
for (int z = 1; z <= count; z++)
{
for (int x = 1; x <= count; x++)
{
Button btn = new Button();
btn.Text = 0.ToString();
btn.Location = new Point(z*30, x*30);
btn.Size = new System.Drawing.Size(30, 30);
btn.BackColor = System.Drawing.Color.White;
btn.MouseClick += new System.Windows.Forms.MouseEventHandler(btnClick);
panel1.Controls.Add(btn);
btnList.Add(btn);
}
}
The code of the event describing the click of the button
public void btnClick(object sender, EventArgs e)
{
Button button = (Button)sender;
button.Text = (int.Parse(button.Text)+1).ToString();
Graphics g = Graphics.FromImage(bmp);
Pen pen = new Pen(Color.Black);
//g.DrawLine(pen, );
pictureBox1.Image = bmp;
}
Maybe the question is very stupid, but I do not understand how to refer to the indexes of the pressed button in the btnClick function.
You have, for every object in C#, a Tag property which is free. You can use it to store the coordinates of your button.
So, insert before you add the btn to the panel1.Controls, something like:
btn.Tag = new Point(z, x);
Then, in the btnClick delegate, to get back your coordinates, you use something like:
Button button = sender as Button;
Point p = button.Tag;
int z = p.X;
int x = p.Y;
You can keep the Button button = (Button)sender; The only difference is that casting can throw an exception but the keyword 'as' can't.
As I am writing this, I see the new comments and your reply. Tag isn't in the delegates like KeyDown but with the properties like Location, Size, Text, etc.
You already store z and x:
btn.Location = new Point(z*30, x*30);
You can do this in the click handler to retrieve them:
int z = button.Location.X / 30;
int x = button.Location.Y / 30;
Thanks for answers.
I add code when generation buttons
btn.Tag = new Point(z, x);
and i use btn.Tag when click on button
Point p = (Point)button.Tag;
int z = p.X;
int x = p.Y;

how can i call a button click method from another class

hello everyone i'm new to c# and wpf programming and
i'm trying to create a dynamic menu where i have + and - buttons which affect a text box which represents quantity. so in a grid i call a class called productcard which i call in a page to fill the grid with the products.
now the problem is how can i use the click event inside of the product card class in my page where i have multiple cards.
class productcard
{
Button plus = new Button();
Button minus= new Button();
public TextBox qtyl = new TextBox();
Grid z = new Grid();
public int left;
public int top;
GroupBox yy;
public GroupBox XX { get { return this.yy; } set { this.yy = value; } }
public productcard(int left , int top )
{
this.left = left;
this.top = top;
Thickness margin = new Thickness(left, top, 0, 0);
Thickness bmar = new Thickness(0, 0, 0, 0);
plus.Height = 30;
plus.Width = 40;
plus.VerticalAlignment = VerticalAlignment.Bottom;
plus.HorizontalAlignment = HorizontalAlignment.Right;
plus.Content = "+";
plus.HorizontalContentAlignment = HorizontalAlignment.Center;
// - button
minus.Height = 30;
minus.Width = 40;
minus.VerticalAlignment = VerticalAlignment.Bottom;
minus.HorizontalAlignment = HorizontalAlignment.Left;
minus.Content = "-";
minus.HorizontalContentAlignment = HorizontalAlignment.Center;
// add the button to the grid
z.Children.Add(plus);
z.Children.Add(minus);
// creat text box
qtyl = new TextBox();
qtyl.Height = 30;
qtyl.Width = 30;
qtyl.Background = Brushes.White;
qtyl.VerticalAlignment = VerticalAlignment.Bottom;
qtyl.HorizontalAlignment = HorizontalAlignment.Center;
qtyl.Text = "0";
// add text box to the grid inside the group box
z.Children.Add(qtyl);
// creat group box
GroupBox yy = new GroupBox();
yy.Margin = margin;
yy.VerticalAlignment = VerticalAlignment.Top;
yy.HorizontalAlignment = HorizontalAlignment.Left;
yy.Content = z;
yy.Height = 150;
yy.Width = 150;
XX = yy;
// insert group box in the produc grid
}
public void plus_Click(object sender, EventArgs e)
{
// this.plus.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
MessageBox.Show(" + has been cliked");
int result=Convert.ToInt32(qtyl.Text)+1;
qtyl.Text = result.ToString();
}
private void minus_Click(object sender, EventArgs e)
{
int result = Convert.ToInt32(qtyl.Text) - 1;
qtyl.Text = result.ToString();
}
}
You can make a handler for your button like this:
Button myButton=new Button();
myButton.Click += delegate(object sender, RoutedEventArgs e) {
//handle event
};
I hope this helps.
Reza is correct in how to write more code for a Button generated in code.
However, I would give you a word of warning that this is not proper WPF usage of MVVM and you might be putting yourself down a path for trouble later.
I would suggest having your view's buttons bind to an ICommand that can be defined in a ViewModel that will handle doing the logic for your text update.
As you mentioned, you're having different view controls represent the data based on your button press. You're currently surviving as the view's are directly updating each other (THIS IS BAD).
The moment you want to represent this data in other views, say you want your button to update 5 labels in 3 different layouts in 2 windows, you're going to have unmaintainable references in your views.
If you have the ViewModel get a command from your view bound to the button, you can have the command logic update the property in the ViewModel that multiple views can be bound to and update them all at the same time via INotifyPropertyChanged.
Not to mention, ICommand can also let you disable buttons cleanly from being clicked.
Consider taking an hour to check out this tutorial to see the separation of View and ViewModel. What you're doing now looks like it's setting you up for a world of hurt later...

How to dynamically create buttons and to add different event handler?

I created a function that appends buttons in a form. Buttons when clicked supposed to open different files. File paths are in listbox1. I want to add a click event for every button I append. One button should open one file from listbox1.
The part with appending buttons works, but I can't add a different event for each of them only one.
This is my code. It adds the event to every button but only the last one.
PlaySong is a function that plays ".mp3" file. That works.
Can someone help me?
int i = 0;
private void Load_Songs()
{
List<string> url = new List<string>();
url = listBox1.Items.Cast<String>().ToList();
int p = 5;
for (int j = 0; j < listBox1.Items.Count; j++)
{
EventHandler klik = new EventHandler(Playing);
Song_Data titl = new Song_Data(url[j]);
Button n = new Button
{
Text = titl.Title,
Location = new Point(0, p + 20),
Width = ClientRectangle.Width / 3,
FlatStyle = FlatStyle.Flat
};
p += 20;
n.Click += klik;
List_Artist.Controls.Add(n);
i++;
}
}
private void Playing(object sender, EventArgs e)
{
PlaySong(listBox1.Items[i].ToString());
}
You don't need many event handlers, just store the index to the button's Tag in your loop and then use it to find which index you should use to choose from listbox:
Button n = new Button
{
Text = titl.Title,
Location = new Point(0, p + 20),
Width = ClientRectangle.Width / 3,
FlatStyle = FlatStyle.Flat,
Tag = j
};
Then in your handler:
private void Playing(object sender, EventArgs e)
{
int i= (int)((Button)sender).Tag;
PlaySong(listBox1.Items[i].ToString());
}
to use different handler for each button you can use anonymous event handler, but won't solve your problem:
n.Click += (s, ev) =>
{
//code when button clicked
};

Change properties of programmatically created buttons

I create buttons in my application by:
List<Button> btnslist = new List<Button>();
for (int i = 0; i < nbrofbtns; i++)
{
Button newButton = new Button();
btnslist.Add(newButton);
this.Controls.Add(newButton);
newButton.Width = btnsidelength;
newButton.Height = btnsidelength;
newButton.Top = btnsidelength
* Convert.ToInt32(Math.Floor(Convert.ToDouble(i / Form2.puzzlesize)));
newButton.Left = btnsidelength
* Convert.ToInt32(
Math.Floor(Convert.ToDouble(i))
- Math.Floor((Convert.ToDouble(i))
/ (Form2.puzzlesize)) * (Form2.puzzlesize));
newButton.BackgroundImage = Lights_out_.Properties.Resources.LightsOutBlack;
newButton.Tag = (i+1).ToString();
newButton.Click += new EventHandler(Any_Button_Click);
Then I have a method for when any of the buttons are clicked.
void Any_Button_Click(object sender, EventArgs e)
{
//the variable b has all the insformation that the single button had itself.
Button b = (Button)sender;
if (b.BackgroundImage == Lights_out_.Properties.Resources.LightsOutBlack)
{
MessageBox.Show(b.Tag.ToString());
MessageBox.Show(btnslist[Convert.ToInt32(b.Tag)].BackgroundImage.ToString());
btnslist[Convert.ToInt32(b.Tag)].BackgroundImage =
Lights_out_.Properties.Resources.LightsOutWhite;
MessageBox.Show(btnslist[Convert.ToInt32(b.Tag)].BackgroundImage.ToString());
}
else
{
MessageBox.Show("b.backgroundimage != lightsoutblack. Backgroundimage = "
+ b.BackgroundImage.ToString());
}
}
How do I change the data in the actual button (then said button is clicked)? I want specificly to change the backgroundimage. How could I do this?? (I also need to change the backgroundimage of some other buttons created by the code.)
The sender object is the button:
Button b = (Button)sender;
... so you should be able to change properties on it directly:
b.WhateverPropsToChange = yourSetting;
PS: I don't think this is necessary, but if the button is not updated directly, you might try to using b.Refresh() to let it know something has changed.
You're handling Click event of every button you've created - and sender in Any_Button_Click is actually the button was clicked.
So just change b.BackgroundImage to whatever you need.

Set Properties via runtime for Multiple Controls

I have a form that contains about 25 Buttons. I want to set the same property for the Multiple buttons based on user input. The properties i want to change are,
Button text
Button Fore Color
Button Back Color
Button Size
I have been able to do this using code but the Code is long. I want to know if there is a way to loop to change all of them.
This is what i used
button1.Text = btntext;
button1.ForeColor = btnforecolor;
button1.BackColor = btnbackcolor;
button1.Size = new Size(btnwidth, btnheight);
I had to do this like this for the 25 button, i want to know if there is any better way to do this with less code??..
Any suggestion will be appreciated.
Two options here:
1) Create a list of buttons and loop:
for (int i = 0; i < 25; i++){
Button btn = new Button();
btn.Text = ...
btn.Location = new Point(10 + (i%5)*100, (i/5)*30);
btn.Click += new EventHandler(btn_Click); // TODO: Implement btn_Click event
this.Controls.Add(btn);
}
2) Loop through your existing controls:
foreach (Control c in this.Controls) {
Button btn = c as Button;
if (btn == null) continue;
btn.Text = ...
}
If you can't iterate through all of the buttons on a form but need a specific list of buttons I use this code.
List<Button> ListOfButtons = new List<Button>
{
this.Button1,
this.Button2,
}
foreach (Button myButton in ListOfButtons)
{
//Do your assigments to myButton
}

Categories