I want to handle LostFocus event of TextBox to perform some actions. But I'm also wouldn't want to perform that actions if TextBox lost it focus because special Button (which opens OpenFileDialog) was clicked or Key.Enter was catched. When Key.Enter was pressed, first of all KeyDown event is raised. Here my event handler of KeyDown:
public void TextBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e != null && sender != null)
if (e.Key == System.Windows.Input.Key.Enter && !String.IsNullOrWhiteSpace(((TextBox)sender).Text))
{
e.Handled = true;
isEnterClicked = true;
((System.Windows.Controls.TextBox)sender).Visibility = System.Windows.Visibility.Collapsed;
}
}
After Key.Enter was pressed, TextBox.Visibility is changed, and this operator will raise LostFocus event.
public void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
try
{
if (!isEnterClicked)
{
DependencyObject dob = (DependencyObject)sender;
while ( !(dob is ItemsControl))
{
dob = VisualTreeHelper.GetParent(dob);
}
dynamic myCmd = dob.GetValue(Control.DataContextProperty);
myCmd.SomeCommand.Execute(((TextBox)sender).GetValue(Control.DataContextProperty));
}
}
finally
{
isEnterClicked = false;
}
}
LostFocus handler firstly watch whether isEnterPressed equals to false, its mean, TextBox lost it focus not because enter was pressed. SomeCommand will delete some item which was bind to TextBox, and it will disappear.
Q: So, how to do the same with Button.Click event?
First of all, BEFORE Button clicked, TextBox lost it focus. The same way is not acceptable. Button.Focusable="False", creating new ControlTemplate or handling Timer.Elapsed event do not satisfy my requirements.
If I understood problem correctly, try to check if button is focused, if so dont perform actions in textbox lostfocus event. If Iam correct button should be focused before textbox lostfocus event raised.
if (!isEnterClicked && !button.Focused)
{
//do stuff
}
Related
I am building a XAML app (winrt) to be used in enterprise. Some forms in the app can be complex: some inputs gets shown/hidden depending on other inputs. I would like to control the tab key navigation using a behavior on all inputs (TextBox, PasswordBow, ComboBox...) to optimize the user activity.
I subscribed to the KeyUp event of the TextBox but the event is not raised when the user strikes the Tab key. As a consequence, the next element in the visual tree is given keyboard focus.
I found not method to override like the winform's IsInputKey.
How can I subscribe to the use of the Tab key on a TextBox?
Is looks like the newly focus element receives the KeyUp event.
What I did is subscribe to the KeyDown event, checked for the Tab key and marked the event as handled.
protected override void OnAttached()
{
var textBox = (TextBox)this.AssociatedObject;
textBox.KeyDown += this.OnKeyDown;
textBox.KeyUp += this.OnKeyUp;
// don't forget to unsubscribe in OnDetached
}
private void OnKeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == VirtualKey.Tab && !e.Handled)
{
e.Handled = this.Work(sender, e);
}
}
private void OnKeyUp(object sender, KeyRoutedEventArgs e)
{
if (e.Key != VirtualKey.Tab && !e.Handled)
{
e.Handled = this.Work(sender, e);
}
}
Here is the method that does the focusing work. The code was in OnKeyUp before I knew how to do.
/// <returns>true if an action has been performed (focus next or execute command)</returns>
private bool Work(object sender, KeyRoutedEventArgs e)
{
var isEnterKey = e.Key == VirtualKey.Enter;
var isTabKey = e.Key == VirtualKey.Tab;
if (/* there is something else to focus */)
{
// focus it
return true;
}
return false;
}
My problem was that the Tab virtual key wasn't being received in the KeyUp event, while other keys (Esc,Enter, alphanumeric keys) were. I just changed it to a KeyDown with the same handler. The difference seems to be imperceptible to the user.
I have a checkbox on which I want to ask the user if he is sure or I will cancel the operation.
I tried the Click event but it turns out it is only being called after the CheckedChanged event.
I thought I could at least do it "ugly" by asking the user inside the CheckedChanged event but then if he wishes to cancel I need to change the Checked value what raises the event all over again.
Another thing I would prefer to avoid with this solution is that even before the user replies, the tick mark appears in the checkbox.
I'm looking for an event that happens before the CheckedChanged or a way to prevent the CheckedChanged event.
Set AutoCheck to false. and handle the Checked state in the Click event.
Find the Sample Code. It just removes the event attached to the checkbox and adds it back
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (checkBox1.Checked)
{
checkBox1.CheckedChanged -= checkBox1_CheckedChanged;
checkBox1.Checked = false;
checkBox1.CheckedChanged += checkBox1_CheckedChanged;
}
}
Adding up to Sievajet's answer.
The AutoCheck property is set to false to prevent automatic update of checkbox's appearance when it is clicked.
See the official documentation of AutoCheck below
Gets or set a value indicating whether the
System.Windows.Forms.CheckBox.Checked
or System.Windows.Forms.CheckBox.CheckState values and the System.Windows.Forms.CheckBox's
appearance are automatically changed when the System.Windows.Forms.CheckBox is
clicked.
Try the ClickEvent Handler Below
private void checkBox_Click(object sender, EventArgs e)
{
if (checkBox.Checked == false)
{
DialogResult result = MessageBox.Show("Confirmation Message", "Confirm",
MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
if (result == DialogResult.OK)
{
checkBox.Checked = true;
}
}
else
{
checkBox.Checked = false;
}
}
I would like to fire a button click event if the user presses enter on a text box but when I do the button is not returning a DialogResult.OK. When I physically click the button it works though. Any ideas?
Here is my parent form code
using (var completedForm = new CompletedForm(Qty))
{
DialogResult result = completedForm.ShowDialog();
if (result == DialogResult.OK)
{
return completedForm.QtyCompleted;
}
MessageBox.Show("Invalid Qty, Please Try Again");
return 0;
}
Here is my child form button click event
private void btnPartialComplete_Click(object sender, EventArgs e)
{
if(tbQtyComplete.Text == "")
{
tbQtyComplete.Text = "0";
}
this.QtyCompleted = int.Parse(tbQtyComplete.Text);
this.Close();
}
And here is my textbox keydown event
private void tbQtyComplete_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Return)
{
btnPartialComplete_Click(null, EventArgs.Empty);
}
}
Any ideas why the textbox event wouldn't cause the button to return a DialogResult.OK?
You should use btnPartialComplete.PerformClick(). By calling PerformClick() you are generating a click event for your button but when you call btnPartialComplete_Click you just executing a function which is registered to be executed when click event of the button is raised. So calling btnPartialComplete_Click is not equal to clicking the button.
I am checking the keycode for a textbox, and I want a certain task to be performed when the user presses Enter.
It has been working perfectly, but the task that I am trying to perform now, usually is done using a mouse click. So on the OK on that task (a FolderBrowserDialog), it keeps calling the dialog control.
Oddly enough, even though the debugger shows me into the if branch, for e it shows {KeyData = LButton|MButton|Back}, but KeyValue is still 13...
I think it may be that the textbox remembers its last entry... True ?
In my troubleshooting, I have added a boolean variable so I only go into FolderBrowser when it is true, I have tried to add and delete a space from the textbox after the Browse, and even clear the textbox... Each attempt seemed to make things worse.
It seemed that I was in a quasi-infinite loop - yet it would go away after lots of "ok"'s, and stepping through, I found that for every letter I type in the textbox, I spend 4 to 5 rounds in the CheckKeys. I don't understand why... Or how to fix it.
I added a "e.Handled" which did me no good.
Here's the code:
private void txtDir_TextChanged(object sender, EventArgs e)
{
this.txtDir.KeyUp += new System.Windows.Forms.KeyEventHandler(CheckKeys);
}
private void CheckKeys(object sender, System.Windows.Forms.KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
if (sender == txtDir && txtDir.Text != "" && System.IO.Directory.Exists(txtDir.Text))
{
btnBrowse_Click(this, e);
}
}
}
Why am I going through this check so many times ? Can I add a different test ? Am I doing something wrong ? (nothing is set as default action, for form or textbox...)
Thank you.
In your code you added handler for KeyUp at TextChanged Event. so, When TextChanged new handler will be added for KeyUp Event. Thats why multiple time each letter is checked. put Handler at Form load event.
e.g. If I have entered five letter in TextBox so, 5 Handler will be added for KeyUp. means Number of KeyUp Event Handler equals to number of time TextChanged Event called.
this.txtDir.KeyUp += new System.Windows.Forms.KeyEventHandler(CheckKeys);
this add new handler for KeyUp event. So, when this line execute new handler will be added.
By putting Handler at Form Load event, you can solve multiple letter checked problem.
Try with,
private void FormLoad(object sender, EventArgs e)
{
this.txtDir.KeyUp += new System.Windows.Forms.KeyEventHandler(CheckKeys);
}
private void CheckKeys(object sender, System.Windows.Forms.KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
if (sender == txtDir && txtDir.Text != "" && System.IO.Directory.Exists(txtDir.Text))
{
btnBrowse_Click(this, e);
}
}
}
And one more thing As I understand your code, you want to execute btnBrowse_Click if Enter pressed in TextBox control. But Enter key not handled with KeyUp event you need KeyDown Event handler to handle Enter key.
Code:
private void FormLoad(object sender, EventArgs e)
{
this.txtDir.KeyDown += new System.Windows.Forms.KeyEventHandler(CheckKeys);
}
private void CheckKeys(object sender, System.Windows.Forms.KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
if (sender == txtDir && txtDir.Text != "" && System.IO.Directory.Exists(txtDir.Text))
{
btnBrowse_Click(this, e);
}
}
}
Use KeyDown event instead of TextChanged and write down e.Handle = True in it.
write down following code in your textBox.KeyDown event:
if (e.KeyCode == Keys.Enter)
{
if (sender == txtDir && txtDir.Text != "" && System.IO.Directory.Exists(txtDir.Text))
{
e.Hanlde = true; //it will be close enter keydown handling at this time
btnBrowse_Click(this, e);
}
}
Replaced TextChanged with KeyDown directly and it works again !
(on a side note, I still don't understand why each letter is tested several times...)
Edit: Now after reading the accepted answer, I do understand...
I want to always Focus on a specific TextBox on my WPF application whenever I click on anything on the application it should always focus on the TextBox.
Add to the TextBox.OnLostFocus event a handler which sets the focus to the TextBox.
There is an event handler MouseLeftMouseButton. When the event handler was triggered, use textbox.Focus() inside the handler.
If i'm right, your intention is to get the keyboard commands and display the char pressed into your textbox even if the focus is on other controls.
If that is the case, you can route the keyboard commands to the root control (control in the top level... eg: window), analyse them and display in the textbox. I'ld try to give examples if that helps.
EDIT:
private void Window_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
if (Keyboard.Modifiers != ModifierKeys.Shift)
{
if (e.Key > Key.A && e.Key < Key.Z)
{
textBox1.Text += e.Key.ToString().ToLower();
}
}
else
{
if (e.Key > Key.A && e.Key < Key.Z)
{
textBox1.Text += e.Key.ToString();
}
}
e.Handled = true;
}