WPF/Forms: Creating a new control programmatically that can have events - c#

I wanted to know if it was possible to create a control from another control and which this new control could process certain events.
For example, lets say we have a Button that once it is clicked on will create a ComboBox. Could this new ComboBox be capable of processing a certain event such as a SelectionChanged event?

Sure thing. Simply provide an event handler and hook it up to the event:
public Window1()
{
InitializeComponent();
Button button = new Button();
button.Click += new RoutedEventHandler(button_Click);
}
void button_Click(object sender, RoutedEventArgs e)
{
ComboBox combo = new ComboBox();
combo.SelectionChanged += new SelectionChangedEventHandler(combo_SelectionChanged);
}
void combo_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// Do your work here.
}

Related

How to properly assign events to dynamically created buttons in c# Winforms?

My intention is to create buttons at runtime and have a click event handler subscribed to them. Once the dynamically created button is clicked, the click eventhandler is unsubscribed, such that the click event only fires once.
At runtime the desired behaviour only works if I create one button and click it immediately . If I create more than one button, than only the last created button unsubscribes from the click event. Did I miss something?
public partial class Form1 : Form
{
Button b;
int counter;
public Form1()
{
InitializeComponent();
}
// create more buttons
private void button1_Click(object sender, EventArgs e)
{
b = new Button();
b.Size = new Size(50, 50);
b.Click += b_Click; // dynamic button click event
this.Controls["flowLayoutPanel"].Controls.Add(b);
}
// dynamic button click eventhandler
void b_Click(object sender, EventArgs e)
{
b.Text = counter.ToString();
b.Click -= b_Click;
counter++;
}
}
Because b member will reference last created dynamic button, so clicking any buttons will remove click event handler of currently referenced button in b variable, which would be last created.
Use sender to access instance of "current" button and remove click event handler only from "current" button.
void b_Click(object sender, EventArgs e)
{
var button = sender As Button;
button.Text = counter.ToString();
button.Click -= b_Click;
counter++;
}
Don't use private member for dynamic button, but local variable
private void button1_Click(object sender, EventArgs e)
{
var button = new Button();
button.Size = new Size(50, 50);
button.Click += b_Click;
this.Controls["flowLayoutPanel"].Controls.Add(button);
}
If you need to reference collection of created button somewhere, you can access them from the controls of flow panel where buttons were added
var dynamicButtons = .
this.Controls["flowLayoutPanel"].Controls.OfType<Button>().ToList();
Or save them to the dedicated collection (in case flow panel has other buttons)

C# - How to write a Leave Event for a textbox that has been created dynamically

I have a dynamically created text box. I want to register a function on the Leave event. How do I do that?
textbox = new TextBox();
try:
textbox.Leave += new EventHandler(textBoxLeave);
actual handler:
private void textBoxLeave(object sender, EventArgs e)
{
// put your code here
}

issue with textbox event handlers

I am still learning how to do with event handler. What I want is: When I click the txtMonday to get focused, then I click the remove button to clear this selected textbox. Problem is: when I click the remove button for the selected textbox, all the unselected textboxes are clear. I only want to remove the selected textbox. How to solve this problem? Your code example much appreciated. Thanks! I am using WPF and C#.
private void btnRemoveClick(object sender, RoutedEventArgs e)
{
TextBox text = new TextBox();
text.GotFocus += new RoutedEventHandler(txtMonday_GotFocus);
txtMonday.Clear();
text.GotFocus += new RoutedEventHandler(txtTuesday_GotFocus);
txtTuesday.Clear();
}
private void txtMonday_GotFocus(object sender, RoutedEventArgs e)
{
}
private void txtTuesday_GotFocus(object sender, RoutedEventArgs e)
{
}
This should do what you want. I suggest you do some more studying about C# though, as your code shows some fundamental misunderstandings.
//you'll need a variable to store the last focused textbox.
TextBox txtLast;
public MainWindow()
{
InitializeComponent();
//add an event for all the textboxes so that you can track when one of them gets focus.
txtSunday.GotFocus += txt_GotFocus;
txtMonday.GotFocus += txt_GotFocus;
txtTuesday.GotFocus += txt_GotFocus;
txtWednesday.GotFocus += txt_GotFocus;
txtThursday.GotFocus += txt_GotFocus;
txtFriday.GotFocus += txt_GotFocus;
txtSaturday.GotFocus += txt_GotFocus;
//default to clearing sunday to avoid exception
//you could also let it clear a new TextBox(), but this is wasteful. Ideally,
//you would handle this case gracefully with an if statement, but I will leave that
//as an exercise to the reader.
txtLast = txtSunday;
}
private void txt_GotFocus(object sender, RoutedEventArgs e)
{
//whenever you click a textbox, this event gets called.
//e.source is the textbox, but since it is is just an "Object" we need to cast it to a TextBox
txtLast = e.Source as TextBox;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
//this will clear the textbox which last had focus. If you click a button, the current textbox loses focus.
txtLast.Clear();
}

GotFocus Event is not coming after created LostFocus Event in C#

I just want to clear the clipboard text if my form LostFocus. What I mean is that if a user copies something using his keyboard or mouse, have to clear it on LostFocus events, then I need to get my text back if my form receives focus again. How can I achieve this?
string sValue = "";
public Form1()
{
InitializeComponent();
this.LostFocus += new EventHandler(Form1_LostFocus);
this.GotFocus += new EventHandler(Form1_GotFocus);
}
void Form1_GotFocus(object sender, EventArgs e)
{
Clipboard.SetText(sValue);
textBox1.Text = Clipboard.GetText();
}
void Form1_LostFocus(object sender, EventArgs e)
{
sValue = textBox1.Text;
Clipboard.Clear();
}
This does not work; the LostFocus event is called, but GotFocus is not getting called. How can I solve this?
To give you a quick answer which works, instead of adding the event handlers to the form itself, add them to the TextBox control:
textBox1.LostFocus += new EventHandler(Form1_LostFocus);
textBox1.GotFocus += new EventHandler(Form1_GotFocus);
If the form contains any visible controls, it will never trigger the GotFocusor the LostFocus events.
But the recommended way to handle this behavior at the form level is to use:
this.Deactivate += new EventHandler(Form1_LostFocus);
this.Activated += new EventHandler(Form1_GotFocus);
or
textBox1.Leave += new EventHandler(Form1_LostFocus);
textBox1.Enter += new EventHandler(Form1_GotFocus);
Microsoft says:
For the Control.GotFocus Event
The GotFocus and LostFocus events are low-level focus events that are
tied to the WM_KILLFOCUS and WM_SETFOCUS Windows messages. Typically,
the GotFocus and LostFocus events are only used when updating UICues
or when writing custom controls. Instead the Enter and Leave events
should be used for all controls except the Form class, which uses the
Activated and Deactivate events.
For the Form.Activated Event
When the application is active and has multiple forms, the active form
is the form with the input focus. A form that is not visible cannot be
the active form. The simplest way to activate a visible form is to
click it or use an appropriate keyboard combination.
For the Control.Enter Event
The Enter and Leave events are suppressed by the Form class. The
equivalent events in the Form class are the Activated and Deactivate
events.
string sVal = "";
public Form1()
{
InitializeComponent();
this.Activated += new EventHandler(Form1_GotFocus);
this.Deactivate += new EventHandler(Form1_LostFocus);
}
void Form1_LostFocus(object sender, EventArgs e)
{
sVal = Clipboard.GetText();
Clipboard.Clear();
}
void Form1_GotFocus(object sender, EventArgs e)
{
Clipboard.SetText(sVal);
}

How to connect text change event in multiple text boxes to a single method (C#)?

When I double click on my text boxes in the designed, it creates a method auto-magically for me. Since I wish the same things to occur in any of the cases, I simply call an auxiliary method from each, like in the code below.
private void TextBox_1_TextChanged(object sender, EventArgs e)
{
TextChanged();
}
private void TextBox_2_TextChanged(object sender, EventArgs e)
{
TextChanged();
}
private void TextChanged(object sender, EventArgs e) { ... }
Now I'd like to know if there's a way (other than going into my design file (which, according to the information in it, shouldn't be attempted to) to connect the actions listeners to the same method and skip the detour via the automatically generated ones.
On the designer page go to the events tab, find the event you are looking for (TextChanged) and manually enter the name of the event handler you wish them all to use.
I usually proceed like this in my projects, if controls are not going to change at runtime (i.e. if all controls in the form are added at design time):
// this is the container's ctor
public MyForm()
{
TextBox1.TextChanged += new EventHandler(UniqueHandler);
TextBox2.TextChanged += new EventHandler(UniqueHandler);
...
TextBoxN.TextChange += new EventHandler(UniqueHandler);
}
void UniqueHandler(object sender, EventArgs e)
{
TextBox source = (sender as TextBox);
// handle the event!
}
If controls will change, it's actually quite similar, it just doesn't happen in the ctor but on-site:
// anywhere in the code
TextBox addedAtRuntime = new TextBox();
addedAtRuntime.TextChanged += new EventHandler(UniqueHandler);
MyForm.Controls.Add(addedAtRuntime);
// code goes on, the new textbox will share the handler
In the properties fold-out (most often to the right of your screen) you should have a thunder icon. That's where all the events are referable.
If you don't see the properties, select the regarded component (the text box in your case), right-mouse it and pick "properties" in the context menu.
You can do it by this way:
void btn1_onchange(object sender, EventArgs e)
{
MessageBox.Show("Number One");
}
void btn1_onchange2(object sender, EventArgs e){
MessageBox.Show("Number Two");
}
public MyForm() {
Button btn1 = new Button();
btn1.Text = "Click Me";
this.Controls.Add(btn1);
btn1.TextChange += new EventHandler(btn1_onchange);
btn1.TextChange += new EventHandler(btn1_onchange2);
}
You could do it in designer view. Instead of double-clicking on an element - go to your buttons' properties, select events tab and then put a proper handler name for adequate event. Voila!
Follow these steps:
Go to the InitializeComponent().
There are three events attached to each text box.
There you shoud be able to see the following.
this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
this.textBox2.TextChanged += new System.EventHandler(this.textBox2_TextChanged);
Replace this with
this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
this.textBox2.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
And then remove the method below
private void TextBox_2_TextChanged(object sender, EventArgs e)
{
TextChanged();
}

Categories

Resources