Visual Studio 2010 TableLayoutPanel with Buttons events - c#

I've made in Visual Studio 2010 in designer mode a TableLayoutPanel (for example 8x8 rowsxcolumns), then I've put in each field of this "matrix" a button. Is there any way how to handle the events centrally? I found that TableLayoutPanel have TabIndexChanged, but I don't know if this will be useful for me.
I'm just trying to find out if is possible this:
I click on second button and get the information on what button I've clicked and will be able to change some of his property - for example icon, or text.
Lets imagine an idea that I will understand tablelayoutpanel as an "matrix" or "array" and I want to work with it something like this:
1)I'll click on button on possition i (or i,j)
2)I'll change the Icon of button on possition i (or i,j)
Is that possible? If yes, how?
Thx

You can have a single method handle all your button click events and then use the sender parameter to modify the image on the button.
e.g.
private void CreateButtons(object sender, EventArgs e)
{
for (int i = 0; 8 < length; i++)
{
for (int j = 0; 8 < length; i++)
{
var btn = new Button() { Text = "Something" };
btn.Click += new EventHandler(btn_Click);
this.tableLayoutPanel1.Controls.Add(btn, i, j);
}
}
}
void btn_Click(object sender, EventArgs e)
{
((Button)sender).Image= SomeMethodThatReturnsAnImage();
}
As an aside the TabIndexChanged would be completely useless to you since its only raised when the TabIndex property of a control gets changed which is typically very rare. You'll rember that the TabIndex property is used to control the order of controls for when the user presses the Tab key.

Sounds like you just need to associate the click event of all your buttons with a single event handler, and then manipulate the clicked button, etc., inside the event handler

Related

Button click event not responding c#

The problem we are having is accessing the click event for a button which is created in the click event of another button i.e. clicking the first button generates a new panel and controls, and we now want the button on this newly created panel to perform an action.
The controls have been declared at the top of the class as follows:
Panel createElementPage = null;
TextBox elementDescription = null;
TextBox elementName = null;
Button continueButton = null;
AuditSystem audit;
Here is an excerpt of the method that generates the new panel, the part that defines the continueButton is written as follows:
public void CE_Click(object sender, EventArgs e)
{
createElementPage.Controls.Add(elementDescription);
continueButton = new Button();
continueButton.Text = "Continue";
continueButton.Location = new Point(700, 500);
continueButton.Size = new Size(100, 50);
createElementPage.Controls.Add(continueButton);
}
We want to access the continueButton's click event handler but the method we have written does not seem to be working. This is what we have so far:
private void continueButton_Click(object sender, EventArgs e)
{
Console.WriteLine(" something");
}
Clicking the button yields no results, and we have tried a few solutions such as implementing a seperate eventHandler method. Does anybody have a fix for this?
You have to actually subscribe to the event:
continueButton.Click += continueButton_Click;
Events need to be told what they should handle. Without that, they won't "listen" to anything.
Friendly note: be careful when adding handlers "on demand" like this (i.e. outside of the designer). It doesn't really apply here (you have a new button each time), but it's fairly easy to accidentally subscribe to a control's event multiple times, and your handler will fire multiple times as a result. It's just nice to be aware of :)

reload the page on button click based on button properties

Some context. I've added inside Page_Load of a class Method1 that generates a repeater and Method2 that generates an array of buttons.
Each button is attached dynamically an event inside Method2.
The buttons will never change, but based on clicking a button the repeated elements should change.
My main problem is/are:
1) when I click a button, the event causes the page to load (Page_Load) which calls Method1, which generates the default repeater, instead of the one associated with my specific event attached to button x from the array of buttons; --> so, I wrapped up Method1 in !isPostBack ... then, nothing happens at all
How would you avoid this? What principles would you use for implementig this?
Attempted so far:
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
GetItems(1, 2); //default values (first time the page is loaded)
GenerateButtons(10);
}
}
private void GenerateButtons(int c)
{
LinkButton[] x = new LinkButton[c];
for(int i=0; i<c;i++)
{
x[i] = new LinkButton();
x[i].Text = (i+1).ToString();
Panel1.Controls.Add(x[i]);
x[i].OnClientClick += new EventHandler(Button_Click);
}
}
protected void Button_Click(object sender, EventArgs e)
{
Button button = (Button)sender; // Which button was clicked;
GetItems(int.Parse(button.Text)-1, 3); //3 is a constant; first argument is index of button extracted from its caption
}
//clicking a button should load the page invoking GetItems() specific to the button pressed (first argument is its index) and should regenerate the buttons, maybe highlighting in some way the one that was previously pressed.
To help performance, it would also help not to regenerate the buttons after a page was first loaded.
I'm working with ASP.NET and C#.
My main problem is Button_Click is never invoked, probably because the buttons are regenerated when clicking a button so their definitions is recreated, including the buttons' events.
Your Button_Click handler would always be fired before the regeneration, anyway; so this is not the problem.
Your problem, however, lies in your x[i].OnClientClick += ... code.
You need to hook up to the .Click event of the LinkButton to listen to the right event.
Like this:
private void GenerateButtons(int c)
{
LinkButton[] x = new LinkButton[c];
for(int i=0; i<c;i++)
{
x[i] = new LinkButton();
x[i].Text = (i+1).ToString();
Panel1.Controls.Add(x[i]);
x[i].Click += new EventHandler(Button_Click); // Use the 'Click' event
}
}
Hope this helps!

Handling an array of buttons

I'm creating a simple game where a melody is played, and buttons that corresponds to notes are supposed to be highlighted.
Then the user is to push the button, and during each click the buttons are to highlighted again. I would like to place all the buttons in the GUI graphically.
Can I add a highLight method to the buttons in the GUI? I know I probably could create a new class that ineherits from some button class and create the buttons in the code but I would prefer to do it graphically.
What is the neatest way to handle the button outputs? I know I could paste in code for each button like
private void button_withIndexA(object sender, EventArgs e)
{
checkIfThisNoteWasCorrect();
highLightThisButton();
setHighLightOffForAllOtherButtons();
}
However, I think it would be neater to collect all buttons in some sort of container class and make a function like
class buttonArrayHandler
{
/*constructors etc*/
private void someButtonWasClicked(object sender)
{
/*Check which button was clicked, and do stuff accordingly*/
}
}
However I don't know how to do that. Suggestions?
You could change the button colors to create a highlight effect, but if it's a game you can use images / graphics for buttons, and swap them to another graphic when clicked.
When you double click on a button / graphic / control, by default it creates a method and links it to the click action for you. Instead click on each control, then the little lightning icon, and under the click action, pick the same method for all of them.
Then in your method cast the object sender to get the original control, for example:
var clickedButton = (Button)sender;
Where (Button) may be (Graphics) or whatever type of control you used as a button.
EDIT:
If you need to access a group of controls, you can either keep a global list of names at the top of the form and loop through them:
public List<string> buttonList = new List<string>() { "button1", "button2" };
void SomeMethod()
{
foreach (var controlName in buttonList)
{
this.Controls[controlName].Text = "TEST";
}
}
Or use a fixed name and number range:
void SomeMethod()
{
for (int i = 1; i <= 2; i++)
{
this.Controls["button" + i].Text = "TEST";
}
}
I would recommend adding the buttons programatically just like Carlos487 mentioned, here is the code segment that I made and could work to your advantage:
public Form1()
{
InitializeComponent();
int topMod = 0;
for (int i = 0; i < 5; i++)
{
MakeButton(i,topMod);
topMod += 20;
}
}
public void MakeButton(int index, int margin)
{
Button currentButton = new Button();
currentButton.Text = "Note" + index;
currentButton.Top += margin;
currentButton.Click += OnButtonClick;
panel1.Controls.Add(currentButton);
}
public void OnButtonClick(object sender, EventArgs e)
{
//checkIfThisNoteWasCorrect();
//highLightThisButton();
//setHighLightOffForAllOtherButtons();
MessageBox.Show("My Action was activated!");
}
As you can see you can place the common functions within the OnButtonClick method like I did here, giving all of the buttons the same event sequence. If you do not want to go through the whole process of programming buttons then you could also just do this:
currentButton.Click += OnButtonClick;

Route multiple buttons to the same routine

I have 10 buttons, 0-9 (button0, button1, button2...). When I click any of these buttons, I would like to perform the same routine on them. I would like to know how to, upon clicking of any of these buttons, direct them to the routine below.
private void button0_Click(object sender, EventArgs e)
{
int newValue;
newValue = Convert.ToInt32(Button.text);
}
I have already gone into the properties of each button, then events, and changed the click event to button0_Click (I would have thought this would add "handles button1.click, button2.click, etc." after "private void button0_Click(object sender, EventArgs e)" but if it does that in the background, that's ok as long as it works.)
I also need to know how to identify the button that has been pressed, which is where I'm at with "Convert.ToInt32(Button.text)" (e.g. button2.text = "2").
You can select the same event handler for all the buttons in the designer (in the event tab of the properties window, select the event and there'll be a drop down with all your defined event handlers).
To get which button has been clicked on, cast the sender argument to a Button and you'll have it.
Button button = (Button)sender;
int value = int.Parse( button.Text );
Edit: Also, the "Handles control.event" syntax only exists in Visual Basic.
Edit: Check out the generated code (Form1.Designer.cs, for example) to see how the events are hooked up.
The C# language doesn't use handles to bind events (as VB does). The code for the actual binding is in the generated code for the form, i.e. in the background as you put it.
The sender property is a reference to the control where the event happened. You just need to cast it to the actual type of the control:
private void button0_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
int newValue = Convert.ToInt32(button.text);
}
As an alternative to using the text of the button (for example if you want to translate the application to different languages, or simply don't want to rely on the text), you can put whatever you like in the Tag property of each button, and retrieve it in the event handler.
You could wire them all up to the same event handler an extract the button from sender e.g.
private void button0_Click(object sender, EventArgs e)
{
var button = sender as Button
if (button != null)
{
int newValue = Convert.ToInt32(Button.text);
}
}

ComboBox show dropdown menu on text selection

I want to show the list of items in a combo box when the user selects the text. I have a touch screen application and it's very difficult to hit the dropdown arrow so I figure I'd show the menu when the text is selected which is often what gets touched. I'm using VS 2008. and suggestions for a touch friendly numeric up down solution in VS2008?
You could use the ComboBox.Click event handler and the ComboBox.DroppedDown property and do something like this:
private void ComboBox1_Click(System.Object sender, System.EventArgs e)
{
ComboBox1.DroppedDown = true;
}
You could also use the same event handler for a numericUpDown and use the mouseposition as well as the position and height of the NumericUpDown to get whether or not the click was above or below the halfway-line of the control by doing something like this (not sure if my math here is perfect, but it worked when I tested it):
if ((MousePosition.Y - this.PointToScreen(NumericUpDown1.Location).Y < NumericUpDown1.Height / 2))
{
NumericUpDown1.Value += 1;
}
else
{
NumericUpDown1.Value -= 1;
}
HTH
I was working on a similar situation. We wanted to make the text area behave the same as the button on the right. (IE the user clicks and gets the drop down box)
davidsbro is similar to what I ended up doing, but we wanted it to close if they clicked again, so the value became dropDown.DroppedDown = !dropDown.DroppedDown;.
The issue with this is that if the user clicks the right button of the drop down box, the dialog box opens, then calls the onClick event.
I solved this situation by tracking the original state via the onmouseover event. If the value has changed, we have to assume that the button on the select box handled the click already.
private bool cbDropDownState = false;
private void dropDown_MouseEnter(object sender, EventArgs e)
{
cbDropDownState = dropDown.DroppedDown;
}
private void dropDown_Click(object sender, EventArgs e)
{
if (dropDown.DroppedDown == cbDropDownState )
dropDown.DroppedDown = !dropDown.DroppedDown;
}

Categories

Resources