Prevent tabkey focus change when usercontrol focused - c#

I have a UserControl like following:
public partial class TextControlBox : UserControl
{
public TextControlBox()
{
Window.Current.CoreWindow.KeyDown += CoreWindow_KeyDown;
}
private void CoreWindow_KeyDown(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.KeyEventArgs e)
{
if(e.VirtualKey == VirtualKey.Tab)
{
//insert tabkey into textbox
}
}
}
The problem is when I add the UserControl into my Mainpage.xaml which also contains other controls, the tab-key moves the focus to the next control but
I would like it to insert a tab character (\t) into my textbox instead.
How can I archive this?
I tried handling the event using e.Handled = true if the tab-key is pressed but this did not work.

It seems that you will need to use UIElement.KeyDown Event instead of the CoreWindow.KeyDown Event. CoreWindow.KeyDown Event will not raise when the Tab key is pressed because it's a system key.
Here is the code that I'm using and it works:
public MyUserControl1()
{
this.InitializeComponent();
this.KeyDown += MyUserControl1_KeyDown;
}
private void MyUserControl1_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Tab)
{
e.Handled = true;
//insert tabkey into textbox
}
Debug.WriteLine("MyUserControl1_KeyDown");
}

Related

NumericUpDown with different increment values

I have a C# WinForm application where I want to implement a NumericUpDown component that increments / decrements its value depending whether or not the control key is pressed on clicking to the arrow button. If the control key is pressed, it should increment by 1, by 0.1 otherwise. Using the ValueChanged event does not work, because the value has already changed. I also tried to use the Click and MouseClick event but they are risen after the ValueChanged Event.
Has anyone an Idea how I can achieve this?
// This method added to either Click or MouseClick event
private void Click_Event(object sender, EventArgs e)
{
if (Control.ModifierKeys == Keys.Control)
{
numSetPoint1.Increment = 1; // Setting the Increment value takes effect on the next click
}
else
{
numSetPoint1.Increment = 0.1m;
}
}
// Event added to ValueChanged
private void ValueChanged_Event(object sender, EventArgs e)
{
// the same here
}
One way to do this is by making a CustomNumericUpDown control and swapping out all instances of the regular NumericUpDown control in your designer file.
Then you can just override the methods that implement the value up-down at the source and call the base class or not depending on the static value of Control.ModifierKeys property.
class CustomNumericUpDown : NumericUpDown
{
public CustomNumericUpDown() => DecimalPlaces = 1;
public override void UpButton()
{
if(ModifierKeys.Equals(Keys.Control))
{
Value += 0.1m;
}
else
{
// Call Default
base.UpButton();
}
}
public override void DownButton()
{
if (ModifierKeys.Equals(Keys.Control))
{
Value -= 0.1m;
}
else
{
base.DownButton();
}
}
}
You can implement it at form level.
https://learn.microsoft.com/en-us/dotnet/desktop/winforms/input-keyboard/how-to-handle-forms?view=netdesktop-6.0
Handle the KeyPress or KeyDown event of the startup form, and set the
KeyPreview property of the form to true.
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.ControlKey)
{
numSetPoint1.Increment = 1;
}
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.ControlKey)
{
numSetPoint1.Increment = 0.1m;
}
}

How to handle Keydown event in Form level after All Child controls handled it?

I have a form with two controls A and B
, A has a key-down event and i show a message box when 'S' is pressed on A control.
And i want to show another message when 'S' is pressed in any other control.
how can I do this ?
Simply what I want is : I should be able to handle a Key-down event after all child controls.
and I should be able to know whether the Event is handle in a child control in Form-level Key-down.
I tried enabling Key-preview but when Key-preview is enabled Form-level event get's fired before child control events. I want child controls first, Then Form level one
I want form level Event to be fired after focused control's key down event is fired.
and I want to check in Form-level event whether the event is handled in focused controls key-down event.
What methods can I use for this ?
Please enlighten me.
you can do the following
here a sample code
Add new project call it EventSample
Add a UserControl call it AControl
Add a UserControl call it BControl
make the AControl BackColor Blue and BControl Red in order to
distinguish from the form
//Form1 code
namespace EventSample
{
public delegate void AfterChildEventHandler(Control control,Keys key);
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
aControl1.OnChildFireEvent += OnChildFireEvent;
bControl1.OnChildFireEvent += OnChildFireEvent;
}
void OnChildFireEvent(Control control, Keys key)
{
MessageBox.Show("Form fired event from " + control.GetType().Name);
}
}
}
//AControl code
namespace EventSample
{
public partial class AControl : UserControl
{
public event AfterChildEventHandler OnChildFireEvent;
public AControl()
{
InitializeComponent();
}
private void AControl_KeyDown(object sender, KeyEventArgs e)
{
MessageBox.Show("A Control fired Key down");
if (OnChildFireEvent != null)
OnChildFireEvent(this, e.KeyCode);
}
}
}
//BControl code
public partial class BControl : UserControl
{
public event AfterChildEventHandler OnChildFireEvent;
public BControl()
{
InitializeComponent();
}
private void BControl_KeyDown(object sender, KeyEventArgs e)
{
MessageBox.Show("B Control fired Key down");
if (OnChildFireEvent != null)
OnChildFireEvent(this, e.KeyCode);
}
}
EDITED
another solution you can make it with less code
define a static event
handle this event inside the form
let each control to invoke this event
namespace EventSample
{
public delegate void AfterChildEventHandler(Control control, Keys key);
public class GlobalEvent
{
public static event AfterChildEventHandler OnChildEventFire;
public static void Invoke(Control control, Keys key)
{
if (OnChildEventFire != null)
OnChildEventFire(control, key);
}
}
}
changes in the A Control
namespace EventSample
{
public partial class AControl : UserControl
{
public AControl()
{
InitializeComponent();
}
private void AControl_KeyDown(object sender, KeyEventArgs e)
{
MessageBox.Show("A Control fired Key down");
GlobalEvent.Invoke(this, e.KeyCode);
}
}
}
changes in the B Control
namespace EventSample
{
public partial class BControl : UserControl
{
public BControl()
{
InitializeComponent();
}
private void BControl_KeyDown(object sender, KeyEventArgs e)
{
MessageBox.Show("B Control fired Key down");
GlobalEvent.Invoke(this, e.KeyCode);
}
}
}
Build the sample and run and try to press any key on A or B then you will find that A will fire then the form
hope it will help you

UserControl click event is slow

I have my UserControl, and I have attached it's click event so I can set it's border style.
public partial class TestControl : UserControl
{
public TestControl()
{
InitializeComponent();
this.Click += Item_Click;
IsSelected = false;
}
public bool IsSelected { get; set; }
void Item_Click(object sender, EventArgs e)
{
if (!IsSelected)
{
IsSelected = true;
this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
}
else
{
IsSelected = false;
this.BorderStyle = System.Windows.Forms.BorderStyle.None;
}
}
}
When I click over the UserControl I get it's border style assigned or removed... this works fine. But if I try to click faster It doesn't respond as I click on the UserControl.
If I click once and then wait and click again it works perfect but I want to increase the click response time, like if it was a button.
Any clue on how do I have this behavior?
If you are clicking very fast, you are getting a Double-Click event. Try using the MouseDown event instead.
But since this is the UserControl's base event, you can just override the method instead of attaching an event handler:
protected override void OnMouseDown(MouseEventArgs e) {
base.OnMouseDown(e);
if (e.Button == MouseButtons.Left) {
// your code here...
}
}

event not being fired

I have made a custom dialog window that inherits ChildWindow
public partial class InputWindow : ChildWindow
{
public InputWindow()
{
InitializeComponent();
}
private void OKButton_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("clicked");
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
}
private void inputTextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
this.OKButton_Click(this, new RoutedEventArgs());
}
}
When I press enter in the tetxbox the event OKButton_Click gets fired ( because message box appears). However, the code (Add Folder) in the event handler below that exists in another class does not get fired! even though the message box appears! Why is this so? and How can I fix it?
InputWindow win = new InputWindow();
win.Title = "Enter New Folder Name";
win.OKButton.Click += (s, e) =>
{
if (!string.IsNullOrWhiteSpace(win.inputTextBox.Text))
{
AddNewFolder(win.inputTextBox.Text);
win.DialogResult = true;
}
};
win.Show();
You're just calling OKButton_click directly from your KeyDown event handler. That's not the same as raising the Click event on the OK button itself - it's just a method call. So it's no wonder that other event handlers for OKButton.Click aren't being called.
I don't know of any way of manually raising the Click event yourself. It sounds like really you should have one common method which is called from both the Click event handler and the KeyDown event handler.

How do I close a form when the ESC key was hit, but only if no Control handled it?

I have a Form that closes itself when the ESC key is pressed, thanks to KeyPreview, ProcessKeyEventArgs, ProcessCmdKey or whatever. But I have a Control on that form that does very relevant things when ESC is pressed (it hides itself) and the Form should not be closed when that happens.
The control uses the KeyDown event and sets the SuppressKeyPress flag to true, but that happens after the aforementioned form key preview, thus having no effect.
Is there some sort KeyPostview ?
How do I not close the form when a Control has a relevant use of a key hit ?
Edit: The control handling ESC is a textbox embedded in a hand-maid ListView. The textbox appears when the user clicks a cell, enabling edition. To validate the new text, ENTER would be nice (that already works, as giving the focus to anything else). To cancel edition, ESC seems most natural.
You are competing Big Time over the Escape key. Along with the Enter key, that's a very important key in the standard Windows user interface. Just drop a button on form and set the form's CancelButton property to some other button, that will suck the keystroke to that button.
To compete with that, you have to create a control that tells Winforms that you really think that the Escape key is more important. That requires overriding the IsInputKey property. Like this:
using System;
using System.Windows.Forms;
class MyTexBox : TextBox {
protected override bool IsInputKey(Keys keyData) {
if (keyData == Keys.Escape) return true;
return base.IsInputKey(keyData);
}
protected override void OnKeyDown(KeyEventArgs e) {
if (e.KeyData == Keys.Escape) {
this.Text = ""; // for example
e.SuppressKeyPress = true;
return;
}
base.OnKeyDown(e);
}
}
OK - this works:
class CustomTB : TextBox
{
public CustomTB()
: base()
{
CustomTB.SuppressEscape = false;
}
public static bool SuppressEscape { get; set; }
protected override void OnKeyDown(KeyEventArgs e)
{
CustomTB.SuppressEscape = (e.KeyCode == Keys.Escape);
base.OnKeyUp(e);
}
}
In your form:
public Form1()
{
InitializeComponent();
this.KeyPreview = true;
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape && !CustomTB.SuppressEscape)
{
this.Close();
}
CustomTB.SuppressEscape = false;
}
Can you check to see what control has the focus first? If there's only one control on your form that does something relevant with the escape key, check to see if that's the control that has the focus before you close the form.
The basic problem is that the form's Dispose method is called when Close is called, so the form is going to close and there's not much you can do about it.
I would get around this by having the UserControl implement a marker interface, say ISuppressEsc. The form's KeyUp handler can then locate the currently focused control and cancel the close if the focused control implements ISuppressEsc. Be aware that you will have to do extra work to find the focused control if it may be a nested control.
public interface ISuppressEsc
{
// marker interface, no declarations
}
public partial class UserControl1 : UserControl, ISuppressEsc
{
public UserControl1()
{
InitializeComponent();
}
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
textBox1.Text = DateTime.Now.ToLongTimeString();
}
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
KeyPreview = true;
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
var activeCtl = ActiveControl;
if (!(activeCtl is ISuppressEsc) && e.KeyCode == Keys.Escape)
{
Close();
}
}
}

Categories