I have a textbox with an _onleave event.
I verify the text in the textbox and generate a messagebox.
In most cases focus moves, to whatever was clicked, once the messagebox clears, but not when it was a checkbox.
Is there any way I can capture what was clicked that generated the _onleave event so that I can assign focus to it ( or in this case click the checkbox) once _onleave code is completed.
I have tried:
Control control = (Control)sender;
control.Select();
Unfortunately, this captures the initial textbox and returns focus to it.
Thanks
To demonstrate with an example
Start a new Windows Form Application. Place on it two textboxes and a checkbox. Use the following code to run the application. The problem is explained above and demonstrated in this sample.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
textBox1.Size=new Size(223,22);
textBox1.Text = "Click here first - has leave event";
textBox2.Size = new Size(111, 22);
textBox2.Text = "Click here second";
checkBox1.Text = "Try clicking checkbox";
}
private void textBox1_Leave(object sender, EventArgs e)
{
MessageBox.Show("If you clicked the textbox, focus should move to it" + Environment.NewLine + "If you clicked the checkbox, checkstate will not change or will it gain focus");
}
}
}
Related
I wanted to focus to a TextBox when I leave an other TextBox.
Let's say I have 3 textboxes. The focus is in the first one, and when I click into the second one, I want to put the focus into the last one instead.
I subscribed to the first textbox's Leave event and tried to focus to the third textbox like: third.Focus(). It gains focus for a moment but then the second one got it eventually (the one I clicked).
Strangely if I replace the second TextBox to a MaskedTextBox (or to any other control), the focus remains on the third one.
Pressing Tab does work though.
These are plain textboxes right from the toolbox.
What is the reason, how can I solve this?
Try to handle Enter event of the textBox2. (In properties window double click on Enter event)
//From Form1.Designer.cs
this.textBox2.Enter += new System.EventHandler(this.textBox2_Enter);
private void textBox2_Enter(object sender, EventArgs e)
{
textBox3.Focus();
}
EDIT:
This code looks very strange, but it works for me. According to this post HERE I use ActiveControl property instead of Focus() method. But behavior of TextBox is very strange because it try to be focused multiple times.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
foreach (Control control in Controls)
{
control.LostFocus += (s, e) => Console.WriteLine(control.Name + " LostFocus");
control.GotFocus += (s, e) =>
{
Console.WriteLine(control.Name + " GotFocus");
if (!requestedFocusToTextBox2) return;
ActiveControl = textBox2; //textBox2.Focus() doesn't work
requestedFocusToTextBox2 = false;
};
}
}
private bool requestedFocusToTextBox2;
private void textBox1_Leave(object sender, EventArgs e)
{
ActiveControl = textBox2;
requestedFocusToTextBox2 = true;
}
}
I have two forms, "FrmRunEntry" and "FrmPartNumEntry". When I enter a value on the FrmRunEntry form, it displays the FrmPartNumEntry from and a combobox. After selecting a value in the combobox, I want to press the ENTER key and carry the selected value from the combobox back to a textbox on the FrmRunEntry form. But I cant get it to work. My combobox and form Keydown events never get triggered. My program just sits on the combobox and does nothing after I press ENTER. I've search the forum extensively and have tried the following solutions without success:
How to pass value from one form into another's combobox
How to get selected items of Combobox from one form to another form in C#
I've also tried a few other solutions that didn't work. I'm a new C# programmer and I admit I don't have a deep understanding of how C# events work. I'm hoping someone can assist in solving this problem and help me understand what I'm doing wrong. Here's the code I'm using:
FORM 1
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace HydroProgram
{
public partial class FrmRunEntry : Form
{
public string selectedPartNumber = "";
public FrmRunEntry()
{
InitializeComponent();
this.ActiveControl = TxtHydro;
TxtHydro.Focus();
}
private void FrmRunEntry_Load(object sender, EventArgs e)
{
//Text Boxes
TxtHydro.CharacterCasing = CharacterCasing.Upper;
if (!string.IsNullOrEmpty(selectedPartNumber))
{
TxtPartNum.Text = selectedPartNumber;
}
}
private void TxtHydro_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
this.Hide();
FrmPartNumEntry f = new FrmPartNumEntry();
f.ShowDialog();
}
}
}
}
FORM 2
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace HydroProgram
{
public partial class FrmPartNumEntry : Form
{
public FrmPartNumEntry()
{
InitializeComponent();
this.ActiveControl = CboPartNum;
}
private void FrmPartNumEntry_Load(object sender, EventArgs e)
{
//Combo Box
CboPartNum.Location = new Point(668, 240);
CboPartNum.Size = new Size(255, 23);
CboPartNum.Focus();
CboPartNum.SelectedIndex = 1;
}
private void CboPartNum_KeyDown(object sender, KeyEventArgs e) <-- NOT BEING TRIGGERED
{
processRequest(e);
}
private void FrmPartNumEntry_KeyDown(object sender, KeyEventArgs e) <-- NOT BEING TRIGGERED
{
processRequest(e);
}
private void processRequest(KeyEventArgs e) <-- NEVER REACHED
{
if (e.KeyCode == Keys.Enter && this.ActiveControl == CboPartNum)
{
this.Hide();
FrmRunEntry f = new FrmRunEntry();
f.selectedPartNumber = Convert.ToString(CboPartNum.SelectedItem);
f.ShowDialog();
}
}
}
}
you can overload the constructor of the form for example
public FrmPartNumEntry()
{
InitializeComponent();
this.ActiveControl = CboPartNum;
}
To This
public public FrmPartNumEntry(int value)
{
InitializeComponent();
this.ActiveControl = CboPartNum;
}
Then store value in a private variable. Then you can use it anyway as you want.
if you want to pass anything simply use an object as a parameter then cast it inside the constructor. for example
public public FrmPartNumEntry(object value)
{
InitializeComponent();
int x = (int) value;
this.ActiveControl = CboPartNum;
}
in your situation where both forms are running.
assume you form1 contains combobox and form2 need the data of it then
Make a static field in form1 and make it public.
use textchanged event in combobox to assign the value to static field
access by form1.staticfieldname from form2.
I am not getting the same result as you describe. When I click on the combo box in the frmPartNumEntry form, then press the “Enter” key… the CboPartNum_KeyDown event fires as expected. So the posted code does not demonstrate what you describe.
In addition and more importantly, your code is “creating” and “hiding” multiple forms that are only displayed once, then hid and never used again. This certainly will cause confusion and problems. One issue is that if you execute the complete code, then try to “exit” the program by clicking the red x in the top right of the form… you may notice that execution does NOT stop. The code continues to run and this is because the hidden forms are technically still executing as they were never closed.
To show this… let us look at the code in the first form FrmRunEntry TxtHydro_KeyDown event. If the user presses the “Enter” key, then the currently displayed FrmRunEntry is hidden…
this.Hide();
Then a new second form FrmPartNumEntry is created and it is displayed using a ShowDialog();… This may appear correct, however there is one big problem with this code… when the user closes the second form and code execution returns to THIS code… the current FrmRunEntry is never UN-HIDDEN.
The code in second form’s FrmPartNumEntry processRequest method follows this same odd pattern, hide the current form, then it creates a NEW FrmRunEntry? ... This is NOT going to be the same FrmRunEntry form which was previously hidden. In reality NOW you have TWO (2) FrmRunEntry forms and one is hidden. If you continue to execute this code, each time the steps are duplicated… 2 NEW forms are created and hidden.
I am confident this is NOT what you want.
The posted duplicate link shows several ways to pass data between forms. In your particular case, one possible solution is the make the ComboBox on the second form a “public” combo box. Then make the following changes to the processRequest method. First, we do not want to “hide” this form… we want to CLOSE it. In addition we do NOT want to create a new FrmRunEntry form, we want to UN-hide the one that was previously hidden. So, in the processRequest all we need is to close the form. Something like…
private void processRequest(KeyEventArgs e) {
if (e.KeyCode == Keys.Enter && this.ActiveControl == CboPartNum) {
this.Close();
}
}
When this form closes, then execution will go back to the first form. Specifically the TxtHydro_KeyDown event. Execution will begin right after the…
f.ShowDialog();
line of code. So it is here where want to UN-Hide/Show the previously hidden FrmRunEntry form. In addition, we want to get the selected ComboBox value from the now closed FrmPartNumEntry. Fortunately, even though the second form is “technically” closed and not displayed… we should still be able to access the “public” variables on the form. As noted previously, if the ComboBox has it's Modifiers property set to public then the following code should work and give the first form access to the second forms ComboBox. Something like…
private void TxtHydro_KeyDown(object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.Enter) {
this.Hide();
FrmPartNumEntry f = new FrmPartNumEntry();
f.ShowDialog();
this.Show();
TxtHydro.Text = f.CboPartNum.Text;
}
}
I hope this makes sense and helps.
Thanks to JohnG, the solution to my problem was amazingly simple. All I needed was a single line of code in the form constructor to subscribe the combobox to the event handler like this:
public FrmPartNumEntry()
{
InitializeComponent();
this.ActiveControl = CboPartNum;
CboPartNum.KeyDown += new KeyEventHandler(CboPartNum_KeyDown); <-- SOLUTION
}
One solution would be to:
on form1 define the variable as static:
public partial class Form1 : Form
{
public static string name = "xxx";
}
then on form2 access the variable from form1:
public partial class Form2 : Form
{
lblName.Text = Form1.name;
}
another option is to use an event. The following is a generic code sample which has Main form with a ComboBox and button. Press the button to show the child form and when the ComboBox selection changes an event is fired for any listeners which Form1 does listen for in a method which first checks to see if the item is in the ComboBox in Form1, if not exists, add it and select it.
Child form (Form2)
using System;
using System.Linq;
using System.Windows.Forms;
using static System.Globalization.DateTimeFormatInfo;
namespace CodeSample
{
public partial class Form2 : Form
{
public delegate void SelectionChange(string sender);
public event SelectionChange OnSelectionChange;
public Form2()
{
InitializeComponent();
MonthsComboBox.DataSource =
Enumerable.Range(1, 12).Select((index) =>
CurrentInfo.GetMonthName(index)).ToList();
MonthsComboBox.SelectedIndexChanged +=
MonthsComboBoxOnSelectedIndexChanged;
}
private void MonthsComboBoxOnSelectedIndexChanged(object sender, EventArgs e)
{
OnSelectionChange?.Invoke(MonthsComboBox.Text);
}
}
}
Form1 main form
Note I use ShowDialog, Show may be used instead.
using System;
using System.Windows.Forms;
namespace CodeSample
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void ShowChildForm_Click(object sender, EventArgs e)
{
var f = new Form2();
f.OnSelectionChange += OnSelectionChange;
try
{
f.ShowDialog();
}
finally
{
f.OnSelectionChange -= OnOnSelectionChange;
f.Dispose();
}
}
private void OnSelectionChange(string sender)
{
if (MonthsComboBox.FindString(sender) != -1) return;
MonthsComboBox.Items.Add(sender);
MonthsComboBox.SelectedIndex = MonthsComboBox.Items.Count - 1;
}
}
}
I need to get a rich text box to scroll slowly when you press a button. I have only found codes that teleport you instantly to the end of a box but I need it to slowly scroll down at a readable pace.
private void button2_Click(object sender, EventArgs e)
{
if (textBox2.SelectionStart <= textBox2.TextLength)
{
textBox2.SelectionStart += 30;
textBox2.ScrollToCaret();
Application.DoEvents();
}
}
This code does scroll but it is to fast and I need to slow it down.
Following the suggestion of Uwe Keim here is the steps you have to do in order to use dot-net-transitions(assuming you are using WinForms).
In your Package Manager Console type:
Install-Package dot-net-transitions -Version 1.2.1
Then press enter.
This will install the NuGet Package so you can use the transitions library.
In your form I assume you have a text box and a button eg:
Right click the button on the form and select properties.
From properties click the event button (it looks like a lighting bolt)
Then double click the Action Click.
This will create the click event for your button and will open the form code behind.
Then put this code in the button click event:
private void button1_Click(object sender, EventArgs e)
{
Transition t = new Transition(new TransitionType_EaseInEaseOut(2000));
t.add(this.textBox1, "Top", 200);
t.run();
}
Note
You need to tell VS that you are using Transition therefor in your form you must declare the following
using Transitions;
I have called my textbox textBox1 you might need to change that reference to the name you have used for your text box.
This would be your form
using System;
using Transitions;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Transition t = new Transition(new TransitionType_EaseInEaseOut(2000));
t.add(this.textBox1, "Top", 200);
t.run();
}
}
}
Using: C# Forms VS2015
What I'm trying to do:
On form1, I have a textbox (tbJobTitle) and a button (bChooseJobTitle -> form2) for a "Job Title" of an employee.
The textbox(enabled=false) displays the chosen Job Title of an employee.
The button bChooseJobTitle opens another form (form2) that has a datagrid and 2 buttons (Choose & Cancel)
using System.Threading;
...
Thread the1;
...
private void bChooseJobTitle_Click(object sender, EventArgs e)
{
the1 = new Thread(OpenNew_tblJobTitle);
the1.SetApartmentState(ApartmentState.STA);
the1.Start();
}
private void OpenNew_tblJobTitle(object obj)
{
Application.Run(new form2());
}
...
I initially set a global string MyVar.Employee_Choose_idJobTitle (default "" ) to store the choosen index primary key if the user selected content and click the Choose button. If the Cancel button is click the MyVar.Employee_Choose_idJobTitle will remain = "".
//... at form2 "Choose" button
private void bChoose_Click(object sender, EventArgs e)
{
MyVar.idJobTitle = dataGridView1.CurrentRow.Cells[0].Value.ToString();
this.Close();
}
private void bCancel_Click(object sender, EventArgs e)
{
this.Close();
}
When form2 is closed either by "Choose" button or "Cancel" button, the focus goes back to form1's bChooseJobTitle button.
How do I trigger this event?
...so that can test if the content of MyVar.idJobTitle is not null and add the proper value to my textbox.
I was looking for the button events like onFocus or activate but could not find any. Do I use form events instead to do this?
Quite simply, use event Form Activate if you like.
private void form1_Activated(object sender, EventArgs e)
{
if (MyVar.idJobTitle != "")
{
tbJobTitle.Text = Choose_idJobTitle;
MyVar.idJobTitle = "";
}
}
I am working on .NET 2.0 with C#. How to make focus the control to picture box after pressing the tab from text box ? Please, give me a solution.
Picturebox control is not selectable control hence it doesn't receive focus. Even if you try to set tabindex and tabstop properties on form load it doesn't get the focus.
Why do you want to set focus to picturebox? Are you using click event of this control as a button click event?
Can you provide some more detail on this, so that we can provide a proper solution for this?
Create a button1, then set its TabIndex less than pictureBox1's; put the button1 on top of pictureBox1. Then on runtime hide it behind pictureBox1. To give visual cue that pictureBox has the focus, set the BorderStyle to Fixed3d, set it to none when it loses focus.
Proof of concept:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace TestPicture
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
button1.SendToBack();
pictureBox1.Click += button1_Click;
}
private void button1_Enter(object sender, EventArgs e)
{
pictureBox1.BorderStyle = BorderStyle.Fixed3D;
}
private void button1_Leave(object sender, EventArgs e)
{
pictureBox1.BorderStyle = BorderStyle.None;
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Test");
}
}
}
You need to enclose your PictureBox in a control that can receive click events.