I dynamically create controls and I'd like to be able to use them outside of the context.
For example a dynamically created label :
i = 0;
while (readerBE.Read())
{
Label labelBE = new Label();
labelBE.Name = "labelBE" + i;
labelBE.Text = readerBE["codeArticleComposant"].ToString();
labelBE.Cursor = Cursors.Hand;
labelBE.Click += new EventHandler(this.labelBE_Click);
i++;
}
And when I try to use the OnClick event to retrieve a value like this :
private void labelBE_Click(object sender, EventArgs e)
{
Console.WriteLine(labelBE.Text);
}
labelBE does not exist in the current context.
You can cast the sender argument:
private void labelBE_Click(object sender, EventArgs e)
{
Label labelBE = (Label) sender;
Console.WriteLine(labelBE.Text);
}
But one thing, you have a while-loop and you always create this Label and you never add it to any container control (like GroupBox, Panel or Form). So you would never create multiple and either the while-loop is wrong and should be replaced with an if or you should add the labels to a collection or parent control (well, you should do that anyway).
You can use the sender object that generated the click :
private void labelBE_Click(object sender, EventArgs e)
{
Console.WriteLine(((Label)sender).Text);
}
However I suggest you read more about Variable scope.
Your problem is that you create a variable inside a method, so this variable is no more accessible once you leave it.
Related
I wrote some code to create an additional textbox during runtime. I'm using the metro framework, but this shouldn't matter for my question.
When you click a button, a textbox is being created by a private on_click event:
private void BtnAddButton_Click(object sender, EventArgs e)
{
MetroFramework.Controls.MetroTextBox Textbox2 = new MetroFramework.Controls.MetroTextBox
{
Location = new System.Drawing.Point(98, lblHandy.Location.Y - 30),
Name = "Textbox2",
Size = new System.Drawing.Size(75, 23),
TabIndex = 1
};
this.Controls.Add(Textbox2);
}
What I want to do now is to use the click event of another button, to remove the Textbox again. What I am not sure about is, if I have to remove just the controll or also the object itself. Furthermore I can neither access the Textbox2 Control nor the object from another place.
private void BtnRemoveTextbox2_Click(object sender, EventArgs e)
{
this.Controls.Remove(Textbox2);
}
This does not work, since the other form does not know about Textbox2. What would be the best way to achieve my goal? Do I have to make anything public and if so, how do I do that?
You have to find it first before you choose to remove it.
private void BtnRemoveTextbox2_Click(object sender, EventArgs e)
{
MetroFramework.Controls.MetroTextBox tbx = this.Controls.Find("Textbox2", true).FirstOrDefault() as MetroFramework.Controls.MetroTextBox;
if (tbx != null)
{
this.Controls.Remove(tbx);
}
}
Here, Textbox2 is the ID of your textbox. Please make sure you're setting the ID of your textbox control before adding it.
You need to find those controls using Controls.Find method and then remove and dispose them:
this.Controls.Find("Textbox2", false).Cast<Control>().ToList()
.ForEach(c =>
{
this.Controls.Remove(c);
c.Dispose();
});
Since the control was created in another form, the current form has no way of knowing it by its instance name.
To remove it, loop through all controls and look for its Name:
private void BtnRemoveTextbox2_Click(object sender, EventArgs e)
{
foreach (Control ctrl in this.Controls)
{
if (ctrl.Name == "Textbox2")
this.Controls.Remove(ctrl);
}
}
I want to ask if i have multiple labels with same function Onclick but with different parameters. How i can handle them without make 30 methods.
I want to make A-Z Filter in windows forms application with C#. I have label for each character (A,B,C,D....,Z). Also i have TreeView with data from DB.
private void labelLetter1_Click(object sender, EventArgs e)
{
//this.labelLetter1.Text
// get value of the label and refresh treeview
}
I want to make this on every characters but without repeat same code.
subscribe an example event to other ones. try like this:
private void labelLetter1_Click(object sender, EventArgs e)
{
Label lbl = (Label) sender;
var text = lbl.Text;
//this.labelLetter1.Text
// get value of the label and refresh treeview
}
now set this event to other labels from Properties window.
The sender parameter is going to be the original object that triggered the event. In your case, it is going to be a Label. This means you could cast the object to a Label.
Additionally you could make a single label_click method and have all labels user that single method.
For example:
private void label_Click(object sender, EventArgs e)
{
String labelText = (sender as Label).Text;
//Your process
}
In Windows Forms project I have this method to set some properties of dynamically created control. In this case I also need to show a tooltip when user hovers mouse over it. This works ok except for one thing, I have no idea how to pass the value of w["text"] to control_MouseEnter.
private void SetProp(ref Control obiekt, Dictionary<string, string> w)
{
obiekt.Name = w["id"];
obiekt.Location = new Point(Convert.ToInt16(w["wspx"]), Convert.ToInt16(w["wspy"]));
obiekt.Height = Convert.ToInt16(w["wys"]);
obiekt.Width = Convert.ToInt16(w["szer"]);
if (w["text"] != "")
{
obiekt.MouseEnter += new EventHandler(control_MouseEnter);
obiekt.MouseLeave += new EventHandler(control_MoouseLeave);
}
}
private void control_MouseEnter(object sender, EventArgs e)
{
toolTip.Show("how to pass a value here ??", (Control)sender, 5000);
}
I have no idea has to pass the value of w["text"] to control_MouseEnter.
You can either link your data with target control directly (for example via Control.Tag property) or indirectly (for example, via global variable/dictionary), or use anonymous delegate and closure to create the local data-context:
obiekt.MouseEnter += (s,e) => {
tooltip.Show(w["text"], (Control)s, 5000);
};
Is there a way to use EventArgs somehow?
No, you can't. Because the args are instantiated within the Control's code exactly at the moment when the mouse event occurs, and you can't control the EventArgs creation from event-subscription point.
How about setting the text into Tag member of Control object?
S.th. like object.Tag = w["text"]; and show it with event handler
I want to get the text of the button whenever I click on it.
The algorithm that I made is where i have a function that is a loop that creates a number of buttons and assigns numbers:
void ListAllPage()
{
if (pageMax < 50)
{
//if page max less than 50
for (int i = 0; i < pageMax; i++)
{
Button newBtn = new Button();
newBtn.Text = i.ToString();
newBtn.Width = 50;
newBtn.Click += page_Clicked;
pageCell.Controls.Add(newBtn);
}
}
}
Now buttons will appear on the screen, their events will be triggered and the function page_Click; will be executed:
public void page_Clicked(object sender, EventArgs e)
{
//inside this function I want to obtain the button number that was clicked by the user. How do I do that?
}
Take note, I must all the functions that I described here,...
My thinking is to feed all the buttons that i created inside the loop to a dictionary..
Dictionary.. it will take variables like this btndic.Add(Button b=new Button,b.text);
But the issue is how to retrieve the buttons,,,
if there is a better way, i would like to hear about it...
instead of using the Click Event -> Use the Command Event: http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.button.oncommand.aspx then you can distinguish which button has been clicked
You just need to cast the sender object to a Button, or more generally, a Control:
public void page_Clicked(object sender, EventArgs e)
{
Control c = sender as Control;
MessageBox.Show("Clicked on " + c.Text);
}
Also, it might be more appropriate to use the Tag property to store your custom information (number). In that case, Text property can be anything you like.
Try this way
public void page_Clicked(object sender, EventArgs e)
{
Button btn=(Button)sender;
}
in your ListAllPage method assign Tag to each button:
newBtn.Tag = i;
In your handler you can obtain button instance from sender:
var clickedButton = (Button)sender;
int pageIndex = (int)clickedButton.Tag;
For example
private void tab_Control_SelectedIndexChanged(object sender, EventArgs e)
{
var menuItem = (TabControl)sender;
Selected_tab(tab_Control.SelectedTab.Name);
}
void Selected_tab(string tabname)
{
TabPage _tabname = tabname; // Error need to be converted
this.tab_Control.SelectedTab = _tabname;
}
In this particular case, you can write
tab_Control.SelectedTab = tab_Control.TabPages[tabname];
In general, if you know that the control you're looking for is directly inside of some container (such as a GroupBox or the form itself), you can write
someContainer.Controls[controlName];
If you don't know what the control's parent is, you can write
this.Controls.Find(controlName, true);
The second parameter tells it to recursively search all containers.