Im trying to make an event of 8 picturebox together this is my code, but when i click it put always the same image, the event its been doing twice, i put a message on the event of pictureboxes and it appears twice.
public partial class Form1 : Form
{
int jug=1;
PictureBox[] PicBox = new PictureBox[9];
Image circu = Image.FromFile("Circulo1.png");
Image cruz = Image.FromFile("Cruz1.png");
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
PicBox[0] = this.pcb0;
PicBox[1] = this.pcb1;
PicBox[2] = this.pcb2;
PicBox[3] = this.pcb3;
PicBox[4] = this.pcb4;
PicBox[5] = this.pcb5;
PicBox[6] = this.pcb6;
PicBox[7] = this.pcb7;
PicBox[8] = this.pcb8;
for (int i = 0; i < 9; i++)
{
PicBox[i].Click += new System.EventHandler(PictureBoxes_Click);
}
}
private void PictureBoxes_Click(object sender, EventArgs e)
{
PictureBox p = (PictureBox)sender;
if (jug == 1)
{
jug = 2;
p.Image = cruz;
}
else
{
jug = 1;
p.Image = circu;
}
}
Try refreshing the pictureboxes with built in function. If that not solve the problem, set picturebox image property to null, then refresh and set the image you want.
Or you try setting click event on the design page of your ide, bind it the same function(in this case Pictureboxes_click)
There is no reason to enter the event twice. Your code actually works. I think maybe you have some other controls in your form which uses the same event. Just make sure that the event is being used only by the pictureboxes.
Another thing to do: Put breakpoint at the event and see what controls appear as sender. This will help you fix your problem.
Use pictureboxes' Tag property to understand which one is entering the event:
for (int i = 0; i < 9; i++)
{
PicBox[i].Tag = i;
}
When code enters the event, you can look at p.Tag to see which one triggered the event.
You have only 2 different images with single instances. Try to clone the images, so each PictureBox gets it's own instance of the image:
private void PictureBoxes_Click(object sender, EventArgs e)
{
PictureBox p = (PictureBox)sender;
if (jug == 1)
{
jug = 2;
p.Image = (Image)cruz.Clone();
}
else
{
jug = 1;
p.Image = (Image)circu.Clone();
}
}
Or you can replace the cloning by using the "FromFile"-method, which automatically creates the new instances:
p.Image = Image.FromFile("Circulo1.png");
Related
I am using VS 2017 for an Visual C# application (.Net 4.6.2, 32 bit) that calls a form from the main form. In that second form the SelectedIndexChanged event is not firing for one of the ComboBoxes. Following is the code. If I have to register the event I don't know how. I originally had copied and pasted the ComboBoxes onto the form. Then I deleted that control and re-added the ComboBoxes from the ToolBox. Any help would be appreciated.
namespace Lottery_C_Sharp
{
public partial class Dialog_Matches_Input_Lotomania : Form
{
MatchesMethods_LM m;
public string[] lotomania_list = new string[10];
public string[] pick10_list = new string[5];
Utilities u;
public Dialog_Matches_Input_Lotomania(MatchesMethods_LM mm)
{
InitializeComponent();
m = mm;
u = new Utilities();
set_combos();
comboBox1.SelectedIndex = 0;
comboBox2.SelectedIndex = 0;
comboBox3.SelectedIndex = 0;
}
private void comboBox3_SelectedIndexChanged(object sender, EventArgs e)
{
MessageBox.Show("comboBox3_SelectedIndexChanged");
if (m.NumCurrLimit == 99)
{
set_lotomania_time_text();
set_lotomania_totals_text();
}
else
{
set_pick10_time_text();
set_pick10_totals_text();
}
}
public void set_combos()
{
set_lists();
comboBox1.Items.Clear();
comboBox2.Items.Clear();
comboBox3.Items.Clear();
if (m.NumCurrLimit == 99)
{
textBox1.Text = "Brazilian LotoMania";
AddToCombo(comboBox1, lotomania_list);
comboBox1.SelectedIndex = 0;
AddToCombo(comboBox2, lotomania_list);
comboBox2.SelectedIndex = 0;
AddToCombo(comboBox3, lotomania_list);
comboBox3.SelectedIndex = 0;
set_lotomania_time_text();
set_lotomania_totals_text();
}
else
{
textBox1.Text = "USA New York Pick 10";
AddToCombo(comboBox1, pick10_list);
comboBox1.SelectedIndex = 0;
AddToCombo(comboBox2, pick10_list);
comboBox2.SelectedIndex = 0;
AddToCombo(comboBox3, pick10_list);
comboBox3.SelectedIndex = 0;
set_pick10_time_text();
set_pick10_totals_text();
}
}
You should register the event for Your desired combobox in Designer properties, like this:
It generates event registration in Form1.Designer.cs (form name depends on how You've named it) auto-generated file:
this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox3_SelectedIndexChanged);
Then Your function, where You can perform some actions when event occures shows in Form1.cs
private void comboBox3_SelectedIndexChanged(object sender, EventArgs e)
{
// Do something
}
You have several options to register the event.
Option 1:
Register in code:
public Dialog_Matches_Input_Lotomania(MatchesMethods_LM mm)
{
InitializeComponent();
...
comboBox1.SelectedIndexChanged += ComboBox_SelectedIndexChanged;
}
Option 2:
Double click on comboBox1 in the designer, this will automatically add and register an event.
Option 3:
Select the comboBox1 in the designer, right click and select "Properties", in the properties window select the event icon on top (the lightning symbol), find "SelectedIndexChanged" and enter the name of the event or double click to automatically add and register an event.
i cant call or use event click of editor button that i create. the screen shot for the button is
the code that i make is like this
RepositoryItemComboBox repositoryItemComboBox1 = new RepositoryItemComboBox();
EditorButton lp = new EditorButton();
private void gridView1_CustomRowCellEdit(object sender, CustomRowCellEditEventArgs e)
{
repositoryItemComboBox1.Items.Clear();
GridView view = sender as GridView;
for (int i = 0; i < gridView1.RowCount; i++)
{
if (gridView1.GetDataRow(i) == null)
{
break;
}
string code = gridView1.GetDataRow(i)["code"].ToString();
if (!repositoryItemComboBox1.Items.Contains(code))
{
repositoryItemComboBox1.Items.Add(code);
}
}
if (e.Column.FieldName == "code" && view.IsFilterRow(e.RowHandle))
{
repositoryItemComboBox1.Buttons.Add(lp);
repositoryItemComboBox1.Buttons[0].Kind = DevExpress.XtraEditors.Controls.ButtonPredefines.Plus;
repositoryItemComboBox1.Buttons[1].Kind = DevExpress.XtraEditors.Controls.ButtonPredefines.Minus;
e.RepositoryItem = repositoryItemComboBox1;
}
when i click the minus nothing happen because no handler(event).
what i want is when i click that minus button it clear gridview filter
FYI : iam using devexpress
You can hook to the repositoryItem's ButtonClick event. In this event, you will know which button has been clicked. So let's say you create your button this way :
private void SomeMethod()
{
var buttonPlus = new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Plus);
var buttonMinus = new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Minus);
repositoryItemComboBox1.Buttons.Add(buttonPlus);
repositoryItemComboBox1.Buttons.Add(buttonMinus);
}
In the repositoryItemComboBox1_ButtonClick, you have access to the button properties in the "e" argument. In this example, i'm using the "Kind" property, but you could use the tag or anything really.
private void repositoryItemComboBox1_ButtonClick(object sender, DevExpress.XtraEditors.Controls.ButtonPressedEventArgs e)
{
if (e.Button.Kind == DevExpress.XtraEditors.Controls.ButtonPredefines.Minus)
{
// do something
}
else if (e.Button.Kind == DevExpress.XtraEditors.Controls.ButtonPredefines.Plus)
{
// do something else
}
}
This is the way I do it.
I'm playing around abit with winforms and its controls and just discovered how to do custommade buttonclicks. However, there is a problem. I've got a loop, that's looping through a list of elements, and if a condition appears - I'm creating a button that will pop up a gridview.
public void draw(ref Panel inputPanel) //draws the eventline
{
int stepCounter = 0;
for (int i = 0; i < DaysList.Count-1; i++)
{
Button b1;
if (DaysList[i].Elements.Count > max)
{
b1 = new Button(); //Create the box
b1.Width = 120;
b1.Height = 40; //Set width and height
b1.Location = new Point(stepCounter + 35, 70); //Location
inputPanel.Controls.Add(b1); //
b1.Text = "Check event date in grid";
b1.Show();
b1.BringToFront();
b1.Click += new EventHandler((sender, e) => btn_Click(sender, e, DaysList[i].Elements));
stepCounter += 200;
}
}
}
That was my method for creating the buttons and a click event for the when my condition appears. The function that is passed to the eventhandler looks like this:
public void btn_Click(object sender, EventArgs e, List<EventElement> inputElems)
{
Button button = sender as Button;
DataGridForm window = new DataGridForm(inputElems);
window.Show();
}
public class EventElement
{
public EventElement()
{
}
public int Count{get;set;}
public string Date{get;set;}
}
The clickpart of the event is fine but whenever i click the spawned buttons, I get the wrong data into the gridview. As an example: The loop has created four buttons for me and they are presented on a straight line on the form. But whenever i click one of the buttons - dosnt matter which one of them, the button always return the data of the last spawned button. A more clear example: lets say we have the list inputElems looks like this:
inputElems[0].Count -> 2644
inputElems[1].Count -> 2131
inputElems[2].Count -> 8467
inputElems[3].Count -> 5462
When i now click the second button, the input to the second buttons parameter list should have the values (sender, e, 2131), right? but for some reason, the last argument gets the same like the 4th element in the list, even though i call the secondly created button.
I figured that it has something to do with me always calling the last added button_click to the eventhandler of the button, if so, how do I call different clicks from the EventHandler?
Instead of passing inputElems with the EventHandler, you can use Tag.
E.g. use:
b1.Tag=i;
Then in your click event handler:
public void btn_Click(object sender, EventArgs e)
{
Button button = sender as Button;
DataGridForm window = new DataGridForm(DaysList[int.Parse(button.Tag.ToString())].Elements);
window.Show();
}
The problem is that the for loop is out of scope, and thus unable to provide you with the data you're looking for. A more straight forward approach might be something like this:
public void draw(ref Panel inputPanel) //draws the eventline
{
int stepCounter = 0;
for (int i = 0; i < DaysList.Count-1; i++)
{
Button b1;
if (DaysList[i].Elements.Count > max)
{
b1 = new Button(); //Create the box
b1.Width = 120;
b1.Height = 40; //Set width and height
b1.Location = new Point(stepCounter + 35, 70); //Location
inputPanel.Controls.Add(b1); //
b1.Text = "Check event date in grid";
b1.Show();
b1.BringToFront();
b1.Tag = DaysList[i].Elements;
b1.Click += btn_Click;
stepCounter += 200;
}
}
}
and then in btn_Click, do this:
public void btn_Click(object sender, EventArgs e)
{
Button button = sender as Button;
int inputElems = (List<EventElement>)button.Tag;
DataGridForm window = new DataGridForm(inputElems);
window.Show();
}
I am creating some picturebox dynamically and click event for picturebox as follows
Image myImage = Image.FromFile("image/Untitled6.png");
PictureBox[] txtTeamNames = new PictureBox[5];
for (int i = 0; i < txtTeamNames.Length; i++)
{
var txt = new PictureBox();
txtTeamNames[i] = txt;
txtTeamNames[i].Image = myImage;
txtTeamNames[i].Height = 53;
txtTeamNames[i].Width = 48;
this.panel1.Controls.Add(txtTeamNames[i]);
txtTeamNames[i].Visible = true;
txtTeamNames[i].Click += new EventHandler(this.clcikeventhandle);
}
When someone clicks on any picture box, how do I find its array index and name?
void clickEventHandler(object sender, EventArgs e)
{
//???
}
You can access the PictureBox via the sender argument. So try this:
PictureBox[] txtTeamNames;
void YourMethod()
{
Image myImage = Image.FromFile("image/Untitled6.png");
txtTeamNames = new PictureBox[5];
//The same as your code
}
void clcikeventhandle(object sender, EventArgs e)
{
int index = txtTeamNames.IndexOf(sender As PictureBox);
}
EDIT: Approach #2
But if you are not happy with declaring that array in the class scope you can try this approach:
//Same as your code
for (int i = 0; i < txtTeamNames.Length; i++)
{
//Save as your code
txtTeamNames[i].Tag = i; // ADD THIS LINE
}
Then:
void clcikeventhandle(object sender, EventArgs e)
{
int index = int.Parse((sender as PictureBox).Tag.ToString());
}
Another suggestion - create a custom class, which inherits from PictureBox. It will have an extra Index property. And you can set it between these two lines:
txtTeamNames[i].Visible = true;
//assign the index here
txtTeamNames[i].Click += new EventHandler(this.clcikeventhandle);
like so:
txtTeamNames[i].Index = i;
Then in the handler:
void clickEventHandle(object sender, EventArgs e)
{
PictureBox pbox = sender As PictureBox;
int index = pbox.Index();
string name = pbox.Name();
}
You keep the same scope of variables, which may be useful if you are concerned about it. If you are okay with upgrading scope of txtTeamNames to class level, see another answer by Hossein Narimani Rad.
namespace your_name_project
{
public partial class Form_Begin : Form
{
PictureBox[] pictureBoxs = new PictureBox[6];
public Form_Begin()
{
InitializeComponent();
pictureBoxs[0] = pictureBox1; pictureBoxs[1] = pictureBox2; pictureBoxs[2] = pictureBox3;
pictureBoxs[3] = pictureBox4; pictureBoxs[4] = pictureBox5; pictureBoxs[5] = pictureBox6;
}
//continue
List<PictureBox> pictureBoxes = new List<PictureBox>();
private void buttonX1_Click(object sender, EventArgs e)
{
for (int i = 0; i <3; i++)
{
pictureBoxs[i].Image =your_name_project.Properties.Resources.image_1;// load image1 and Image_2from resource in property of picturebox
}
for (int i = 3; i < 6; i++)
{
pictureBoxs[i].Image = your_name_project.Properties.Resources.Image_2;
}
}
}
}
I've tried the 1st approach cited above, but it did not work for me. I needed to change the syntax in order to work. I am unsure why, but my way for approach 1 to work would be:
PictureBox[] txtTeamNames;
void YourMethod()
{
Image myImage = Image.FromFile("image/Untitled6.png");
txtTeamNames = new PictureBox[5];
//The same as your code
}
void clcikeventhandle(object sender, EventArgs e)
{
int index = Array.IndexOf(txtTeamNames, sender); //DIFFERENT HERE
}
If anyone has an idea...
I want to implement Nine Men's Morris Game.
I have a board with 24 pictureboxes and on the left and right side, 9 red pictureboxes and 9 green pictureboxes.
I want to add them in a list:
List<PictureBox> ls = new List<PictureBox>();
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 1; i <= 24; i++)
{
PictureBox p = new PictureBox();
p.Name = "pictureBox" + i;
ls.Add(p);
}
}
is it ok?
and is it possible to do something like this: I want to click on one of the 24 pictureboxes, and make the background of that picturebox to become one time green and one time red?
I mean recursive function or something like that that can recognize when i click on a picturebox, search in the list for that picturebox and changes his backcolor?
You don't need any pictureBox list here.
for (int i = 1; i <= 24; i++)
{
PictureBox p = new PictureBox();
p.Click += p_Click;
//of course, somecontrol.Controls.Add(p);
//for ex: this.Controls.Add(p);
}
-
void p_Click(object sender, EventArgs e)
{
((PictureBox)sender).BackColor = Color.Green;
}
EDIT
It seems you are trying to add an event handler to all pictureBoxes
**parentControl**.Controls.OfType<PictureBox>()
.ToList().ForEach(p => p.Click+=p_Click);
I assume the list of 24 PictureBoxes is supposed to represent the points on a nine man morris board where the player's men can be positioned.
I4V is right that all you need to do is add a click handler to each picture box. If you want to have the background alternate between green and red, keep your original list, but add the click handler in it
for (int i = 1; i <= 24; i++)
{
PictureBox p = new PictureBox();
p.Name = "pictureBox" + i;
p.Click += p_Click; // <----------
ls.Add(p);
}
And modify i4v's click handler to use the current background color to determine the new background color.
void p_Click(object sender, EventArgs e)
{
PictureBox p = (PictureBox)sender);
p.BackColor = p.BackColor == Color.Green ? Color.Red : Color.Green;
}
A couple of other points.
You don't set an initial background color, so it will be the default color until clicked on, when it will be set to Green (as Green isn't the default background color).
Why name your pictureboxes w/ their List index + 1? Why not just use the List index and the natural C# iteration from 0: for (int i = 0; i < 24; i++)?
The method you have outlined would not work, however there is another way to do the same thing using the sender object passed into the event handler:
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 1; i <= 24; i++)
{
PictureBox p = new PictureBox();
p.Name = "pictureBox" + i;
p.Click += PictureBox_Click;
}
}
void PictureBox_Click(object sender, EventArgs e)
{
PictureBox event_picturebox = (PictureBox)sender;
event_picturebox.BackColor = Color.White;
}
You just have to map every picture box you want to run this event to the same event, the event will then be able to perform actions on this pictureBox because a reference to it was passed in.
If you already have the picture boxes defined in the form, you just need to do something like:
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.Click += PictureBox_Click;
pictureBox2.Click += PictureBox_Click;
// and keep going
// OR
// this is a bit dangerous if you don't want ALL
// your picture boxes to have this event
// also assumes that you know picturebox1 exists.
foreach (object f in this.Controls)
{
if (f.GetType().Equals(pictureBox1.GetType()))
{
((PictureBox)f).Click += button_Click;
}
}
}