Passing a Variable to an Event in .NET - c#

For example I have a list of picture boxes that raise an event once the cursor hover over them.
Yet I need somehow not only to rise this event, but also to pass the "i" variable, so that I would know which picturebox has the cursor over it.
for (int i = 0; i < 25; i++)
{
....
pbList.Add(new PictureBox());
pbList[i].MouseHover += new System.EventHandler(this.beeHideInfo);
//// need to pass "i" here
}
and
private void beeShowInfo(object sender, EventArgs e)
{
lb_beeInfo.Text = "You are hovering over: "+beeList[i].name;
/// need to get this "i"
}
Any ideas?

You cannot pass variables to an event.
Besides, the necessary variable has already been passed to you: sender.
sender is a reference to the object which raised the event. In your case, it's a reference to the PictureBox that raised the event.

The object sender parameter is the PictureBox sending the event. If you need to associate something with that object, you can use its Tag member:
for (int i = 0; i < 25; i++)
{
....
pbList.Add(new PictureBox() { Tag = beeList[i] });
pbList[i].MouseHover += new System.EventHandler(this.beeHideInfo);
}
and
private void beeShowInfo(object sender, EventArgs e)
{
PictureBox pb = (PictureBox)sender;
Bee b = (Bee)pb.Tag;
lb_beeInfo.Text = "You are hovering over: "+b.name;
}

Assuming pbList and beelist contain related items in the same order, you can do something like beeList[ pbList.IndexOf(sender) ].name

You could you do something like:
for (int i = 0; i < 25; i++)
{
...
pbList.Add(new PictureBox());
var index = i;
pbList[i].MouseHover +=
delegate
{
lb_beeInfo.Text = "You are hovering over: "+beeList[index].name;
};
}
I.e. use an anonymous method.
As John Saunders says, there is an easier solution.

The easiest way to do this is use an anonymous function to explicitly pass the PictureBox or index instance into the handler.
for (int i = 0; i < 25; i++)
{
....
var box = new PictureBox();
pbList.Add(box);
box.MouseHover += delegate { this.beeShowInfo(box); }
}
private void beeShowInfo(PictureBox box)
{
lb_beeInfo.Text = "You are hovering over: "+box.Name;
}

another way might be if you create a Custom Picture Box
class CustomPictureBox : PictureBox
{
public int id;
public CustomPictureBox(int ID)
{
id = ID;
}
}
firt place a GLOBAL id to parent and each time if a CustomPicureBox is clicked get the ID
than everywhere you want to make changes to Clicked CustomPicutreBox test it
foreach(CustomPicutreBox i in Control.controls)
{
if(i.ID == sender.ID)
doWhatEveryYouWant();
}
}

Related

C#: Retrieve the source of a fired event without the sender object

I'm using the GMaps.NET Controls and I catch the event "TileLoadComplete":
http://www.nudoq.org/#!/Packages/GMap.NET.WindowsForms/GMap.NET.WindowsForms/GMapControl/E/OnTileLoadComplete
I create several controls at run-time and all of them share the same function for that event:
for (int i = 0; i < 5; i++)
{
GMap.NET.WindowsForms.GMapControl control = new GMap.NET.WindowsForms.GMapControl();
control.Manager.Mode = AccessMode.ServerOnly;
control.MapProvider = GMap.NET.MapProviders.GoogleSatelliteMapProvider.Instance;
control.OnTileLoadComplete += Control_OnTileLoadComplete;
// set other map properties
}
private void Control_OnTileLoadComplete(long ElapsedMilliseconds)
{
// who has completed the loading?
}
Because there is no sender object in the event signature, I wonder if there is another way to know which control has completed the loading of the map.
Would this work? Use a lambda to capture the sender:
for (int i = 0; i < 5; i++)
{
GMap.NET.WindowsForms.GMapControl control = new GMap.NET.WindowsForms.GMapControl();
//...snip...
control.OnTileLoadComplete += x => Control_OnTileLoadComplete(control, x);
}
private void Control_OnTileLoadComplete(object sender, long ElapsedMilliseconds)
{
// who has completed the loading?
// the sender, that's who!
}
You'd have to update each usage of Control_OnTileLoadComplete to use that lamdba. You can change the type from object sender to GMapControl sender if the only 'senders' are of type GMapControl.

change local function

I have problem with my C# WinForms project. I have a function that should change the place of buttons if they touch each other. For example, if I have btn1 at oldloction = (4,2) and btn2 at oldlocaction (2,6), then if I will move the buttons and they will touch bt1 new location = (2,6) and bt2 new location = (4,2)
now i did that with 2 buttons and it works.
locationx - means the x location on the button and its orgenize firat place of the location feat to the first buttons[0], the second feat to locationx[1] = buttons[1].location.x;
location - works the same ass locationx but uts the y locaion.
private void myText_MouseUp(object sender, MouseEventArgs e)
{
Point oldlocation = new Point(locationx[0], locationy[0]);
Point oldlocation2 = new Point(locationx[1], locationy[1]);
if (buttons[0].Location.Y == buttons[1].Location.Y)
{
buttons[1].Location = oldlocation;
buttons[0].Location = oldlocation2;
}
}
When I tried to make that as a global function it doesn't work and I don't know why.
This is the code of the global function that doesn't work:
private void myText_MouseUp(object sender, MouseEventArgs e)
{
for (int i = 0; i < counter; i++)
{
Point oldlocation = new Point(locationx[i], locationy[i]);
for (int j = 0; j < counter; j++)
{
if (i != j)
{
Point oldlocation2 = new Point(locationx[j], locationy[j]);
if (buttons[i].Location.Y != buttons[j].Location.Y)
{
buttons[j].Location = oldlocation2;
buttons[i].Location = oldlocation;
}
else if (buttons[i].Location.Y == buttons[j].Location.Y)
{
buttons[j].Location = oldlocation;
buttons[i].Location = oldlocation2;
}
}
}
}
}
Try using the button event for when it is pressed to call the function, rather than creating your own.
If the second function is not part of the control or form containing the buttons, it won't have a way to access the buttons array or locationx and locationy. You may need to pass these values as arguments to your function or ensure that they are provided as members of the class containing the second function. Note that generally a utility function would not take in "sender" and "MouseEventArgs" - pass only the specific data that the utility function needs to do its job.

Create button during runtime in C#.net?

I know how to create button during runtime.
Button button1 = new Button();
button1.Location = new Point(20,10);
button1.Text = "Click Me";
// adding to groupBox1
groupBox1.Controls.Add(button1);
But the problem is i want to add multiple buttons like this..
for(int i = 1; i < 30; i++) {
Button button[i] = new Button();
// Button customization here...
...
groupBox1.Controls.Add(button[i]);
}
The code above is false code. How can I make this happen true in C#.net? i want to create multiple buttons with button name, button1, button2, button3, button4, .... button30;
You can't declare extra variables at execution time in C# - but you really don't want to anyway, as you wouldn't be able to access them dynamically afterwards. Just create an array:
// buttons would be declared as Button[] as a member variable
buttons = new Button[30];
for(int i = 0; i < buttons.Length; i++) {
buttons[i] = new Button();
// Button customization here...
...
groupBox1.Controls.Add(buttons[i]);
}
Alternatively, use a List<Button>, which will certainly be more convenient if you don't know how many buttons you need beforehand. (See the obligatory "arrays considered somewhat harmful" blog post.)
Of course, if you don't actually need to get at the buttons later, don't bother assigning them to anything visible outside the loop:
for(int i = 0; i < 30; i++) {
Button button = new Button();
// Button customization here...
...
groupBox1.Controls.Add(button);
}
You need to think about what information you need access to when... and how you want to access it. If you logically have a collection of buttons, you should use a collection type variable (like a list or an array).
Frankly I think it's one of the curses of the VS designers that you end up with horrible names such as "groupBox1" which carry no information beyond what's already in the type declaration, and encourage developers to think of collections of controls via individually-named variables. That's just me being grumpy though :)
Try this
for(int i = 1; i < 30; i++) {
Button button = new Button();
// Button customization here...
button.Name = "Button" + i.ToString();
groupBox1.Controls.Add(button);
}
You seem like you're almost on the right track:
// in form class
Button[] m_newButtons = new Button[30];
// in your trigger function
for(int i = 0; i < 30; ++i)
{
m_newButtons[i] = new Button();
// ...
groupBox1.Controls.Add(m_newButtons[i]);
}
If you try and do this more than once you may have to remove the old buttons from the control before adding the new ones.
buttons = new Button[30];
for(int i = 0; i < buttons.Length; i++) {
buttons[i] = new Button();
groupBox1.Controls.Add(buttons[i]);
}
this code will work but button will be added one over other so set location also
buttons = new Button[30];
for(int i = 0; i < buttons.Length; i++)
{
buttons[i] = new Button();
Point p=new Point(xvalue,yvalue);
buttons[i].Location = p;
groupBox1.Controls.Add(buttons[i]);
}
one thing you want to remember increment the x or y position by which you want to display it
Try this one out, I have just learned it myself:
public partial class Form1 : Form
{
Button[] btn = new Button[12];// <--------<<<Button Array
public Form1()
{
InitializeComponent();
}
private void Form1_Load (object sender, EventArgs e)
{
for (int i = 0; i < 12; i++)
{
btn[i] = new Button ( );
this.flowLayoutPanel1.Controls.Add(btn[i]);
}
}
// double click on the flow layoutPannel initiates this code
private void flowLayoutPanel1_Paint(object sender, PaintEventArgs e)
{
}
}

Click Event for multiple Textboxes

So I need a way for when a person clicks on a textbox inan 8x8 grid of textboxes, the text in the textbox they have clicked on is changed to something. My grid is set up in a variable called textboxes[,] so if you type textboxes[0,0] you get the first box in the grid. As of now, with my very limited knowledge, I have this.
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
textboxes[i, j].Click += new EventHandler(textboxes_Click);
}
}
Then I can handle whenever one of the boxes is clicked. If you have a better way of doing this, I would love to hear it.I just dont know how to access the box that was clicked, mainly the text. Hope I have explained this well enough. Thanks for all the help!
-Lewis
Your approach is good. You only have to define some additional information to handle it in the event, as follows:
We can define a class to store the textbox position:
public class GridIndex
{
//stores the position of a textbox
public int ipos { get; set; }
public int jpos { get; set; }
}
Your piece of code sightly modified:
for (int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++)
{
textboxes[i, j].Click += new System.EventHandler(this.textBox_Click);
textboxes[i, j].Tag = new GridIndex() { ipos = i, jpos = j };
}
And then your handler:
private void textBox_Click(object sender, EventArgs e)
{
TextBox textBox = sender as TextBox;
if (textBox != null)
{
//Here your have the text of the clicked textbox
string text = textBox.Text;
//And here the X and Y position of the clicked textbox
int ipos = (textBox.Tag as GridIndex).ipos;
int jpos = (textBox.Tag as GridIndex).jpos;
}
}
Edit: I did some changes to the code, please, review.
Your EventHandler has an object called sender as parameter. You have to cast it to an TextBox, then you can get the text of the textbox.
Your event handler has the signature:
void Handler(object sender, EventArgs args)
Where sender is a reference to the TextBox that was clicked. If you also need to know i * j at this point I'd created a class that derives from TextBox which has those numbers stored within it.
You can get the text box values by writting the following code
TextBox txt= (TextBox)sender;
string text = txt.Text.ToString();
MessageBox.show(text);
Hope this will be help full for u

How to add Buttons in WinForm in Runtime?

I have the following Code :
public GUIWevbDav()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
//My XML Loading and other Code Here
//Trying to add Buttons here
if (DisplayNameNodes.Count > 0)
{
for (int i = 0; i < DisplayNameNodes.Count; i++)
{
Button folderButton = new Button();
folderButton.Width = 150;
folderButton.Height = 70;
folderButton.ForeColor = Color.Black;
folderButton.Text = DisplayNameNodes[i].InnerText;
Now trying to do GUIWevbDav.Controls.Add
(unable to get GUIWevbDav.Controls method )
}
}
I dont want to create a form at run time but add the dynamically created buttons to my Current Winform i.e: GUIWevDav
Thanks
Just use this.Controls.Add(folderButton). this is your form.
Problem in your code is that you're trying to call Controls.Add() method on GUIWevbDav which is the type of your form and you can't get Control.Add on a type, it's not a static method. It only works on instances.
for (int i = 0; i < DisplayNameNodes.Count; i++)
{
Button folderButton = new Button();
folderButton.Width = 150;
folderButton.Height = 70;
folderButton.ForeColor = Color.Black;
folderButton.Text = DisplayNameNodes[i].InnerText;
//This will work and add button to your Form.
this.Controls.Add(folderButton );
//you can't get Control.Add on a type, it's not a static method. It only works on instances.
//GUIWevbDav.Controls.Add
}
You need to work with Control.Controls property.
In Form Class Members you can see Controls property.
Use it like this :
this.Controls.Add(folderButton); // "this" is your form class object.

Categories