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

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.

Related

How to raise a dynamically created event on a dynamically created winform control?

I have a CheckedListBox control that I created programatically from below...
Button btnSelectAll = new Button();
btnSelectAll.Text = "Select All";
btnSelectAll.Name = item.Id;
btnSelectAll.Tag = param.Id;
CheckedListBox chkListBox = new CheckedListBox();
chkListBox.Size = new System.Drawing.Size(flowPanel.Size.Width - lblListBox.Size.Width - 10, 100);
//set the name and tag for downstream event handling since two-way bindings are not possible with control
chkListBox.Tag = param.Id;
chkListBox.Name = item.Id;
chkListBox.ItemCheck += new ItemCheckEventHandler(chkListBox_ItemCheck);
btnSelectAll.Click += new EventHandler(btnSelectAll_Click);
Notice when I dynamically created the item, I also added an event handler whenever the ItemCheck on the chkListBox is hit. Somewhere else in the code... I do...
CheckedListBox tmpCheckedListBox = cntrl as CheckedListBox;
for (int i = 0; i < tmpCheckedListBox.Items.Count; i++)
{
tmpCheckedListBox.SetItemChecked(i, true);
}
When I do the above, it doens't raise the ItemChecked event. How do I raise this event such that it is as if a user clicked on the item?
One way is to just call the same method as assigned to the event and pass in the correct control for sender, for example:
for (int i = 0; i < tmpCheckedListBox.Items.Count; i++)
{
tmpCheckedListBox.SetItemChecked(i, true);
chkListBox_ItemCheck(tmpCheckedListBox.Items[i],null);
}
You can usually get away with passing EventArgs.Empty or null as the event arguments, however if you depend on them in the event handler you would need to construct the correct arguments class and pass that in, for example:
for (int i = 0; i < tmpCheckedListBox.Items.Count; i++)
{
var args = new ItemCheckEventArgs(i,true,tmpCheckedListBox.GetItemChecked(i));
tmpCheckedListBox.SetItemChecked(i, true);
chkListBox_ItemCheck(tmpCheckedListBox.Items[i],args);
}

Associate a keypress event with a event handler in a array of textboxes

I've an array of textboxes that generates run-time a variable number of textboxes such the value of a textbox already created into the form.
int n;
TextBox[] tb;
public void AggiungiArmoniche()
{
n = int.Parse(textBox4.Text);
tb = new
TextBox[n];
for (int i = 1; i < tb.Length; i++)
{
tb[i] = new TextBox();
tb[i].Name = "textBox" + i;
tb[i].Location = new Point(100 *i, 163);
tb[i].Size = new Size(48, 20);
tb[i].KeyPress += System.Windows.Forms.KeyPressEventHandler(textBoxP_KeyPress);
groupBox1.Controls.Add(tb[i]);
}
}
private void textBoxP_KeyPress(object sender, KeyPressEventArgs e)
{
// statements of the event
}
When I move to the line in which i associate the event to the event-handler it gives the error it isn't a valid construct in the contest" (in particular in the word keypresseventhandler)
is there a syntactical error in the association?
Remove the KeyPressEventHandler and add the event handler like so
tb[i].KeyPress += textBoxP_KeyPress;
new
tb[i].KeyPress += new System.Windows.Forms.KeyPressEventHandler(textBoxP_KeyPress);

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.

Passing a Variable to an Event in .NET

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();
}
}

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