Richtextbox - on undo? - c#

I need to be able to detect if an "undo" has been triggered, and whether or not it has had an effect on the contents of my RichTextBox.
Of I type content into the RichTextBox at the minute, and press Ctrl+Z, windows seems to handle the undo for me. I want to be able to write code that will get triggered straight after that. I have been looking around and can't find anything.
Thanks in advance.

Starting from .Net 3.0, there is a simple built-in way to get notified when an undo command (among others) is executed:
CommandManager.RegisterClassCommandBinding(typeof(MyClass),
new CommandBinding(ApplicationCommands.Undo, OnUndo));
Just call this line of code in the static constructor (or somewhere else) and add a static method:
private static void OnUndo(object sender, ExecutedRoutedEventArgs e)
{
//your code
}

WINFORM:
You could exploit the KeyDown event and detect if Ctrl+Z is pressed:
richTextBox.KeyDown += new KeyEventHandler(richTextBox_KeyDown);
private void richTextBox_KeyDown(object sender, KeyEventArgs e){
if (e.Modifiers == Keys.Control && e.KeyCode == Keys.Z){
//undo detected, do something
}
}
WPF :
richTextBox.KeyUp += new KeyEventHandler(richTextBox_KeyUp);
void richTextBox_KeyUp(object sender, KeyEventArgs e) {
if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.Z) {
//undo detected, do something
}
}

I think you're going to have to implement that yourself. I'm not aware of an event out of the box that will suit your needs.
You might also want to have a look at Monitored Undo Framework.
And here for additional reading.

If I well understand you, you want to compare content before and after the Ctr+Z.
Then you should do :
In XAML File :
<RichTextBox PreviewKeyDown="RichTextBox_PreviewKeyDown" KeyUp="RichTextBox_KeyUp" />
In CS File :
private void RichTextBox_KeyUp(object sender, KeyEventArgs e)
{
if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.Z)
{
Console.WriteLine("After : " + new TextRange(((RichTextBox)sender).Document.ContentStart, ((RichTextBox)sender).Document.ContentEnd).Text);
}
}
private void RichTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.Z)
{
Console.WriteLine("Before : " + new TextRange(((RichTextBox)sender).Document.ContentStart, ((RichTextBox)sender).Document.ContentEnd).Text);
}
}
Then, you will see in the output of your application the content of your RichTextBox before the Ctrl+Z and the content after.
I've try it and it works fine !

As already described, CommandBindings can be used. I prefer binding to each control instead of binding to all controls of a specific class. This can be done in the following way:
this.richTextBox.CommandBindings.Add(
new CommandBinding(ApplicationCommands.Undo, this.RichTextBoxUndoEvent));
private void RichTextBoxUndoEvent(object sender, ExecutedRoutedEventArgs e)
{
e.Handled = true;
this.richTextBox.Undo();
}

Related

UWP Ctrl+F implementation

I'm creating an UWP app (C# .NET) where there is textbox. I want to implement a shortcut (Ctrl+F) to search texts in the textbox. I know how to find texts, but I don't know how to implement the shortcut.
I found this:
if ((e.Control && e.KeyCode == Keys.F) || (e.Control && e.KeyCode == Keys.S))
{
//do something
}
...but it isn't working for UWP. I tried this (textarea is name of textbox):
private void textarea_KeyDown(object sender, KeyRoutedEventArgs e)
{
if ((e.Key == Windows.System.VirtualKey.Control) && (e.Key == Windows.System.VirtualKey.F))
{
flayoutFind.ShowAt(appBarButtonFind as FrameworkElement);
}
}
but it isn't working too. How can I do it?
And for the future, is there any way, how to override default functionality and shortcut of textbox Ctrl+Z (undo)?
You should be using "Accelerators" and "Access keys" as described here:
https://learn.microsoft.com/en-us/windows/uwp/input-and-devices/keyboard-interactions
Basically, you will have to register for events
Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated += Dispatcher_AcceleratorKeyActivated;
private void Dispatcher_AcceleratorKeyActivated(CoreDispatcher sender, AcceleratorKeyEventArgs args)
{
//Implementation
}
You can check the sample in detail here: https://github.com/Microsoft/DesktopBridgeToUWP-Samples/blob/master/Samples/SQLServer/BuildDemo/MainPage.xaml.cs

How to perform action when Shift+Enter is pressed?

I have a TextBox in a C#/XAML desktop app and I want to detect the Shift+Enter command. How can I do this?
So far I have only been able to find information on commands like Ctrl+A, etc.
ModifierKeys.Shift allows you to identify key pressed combinations which includes Shift:
private void HandleKeyDownEvent(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter && (Keyboard.Modifiers == ModifierKeys.Shift))
{
// Handle..
}
}
Another option is Keyboard.IsKeyDown static method (see Shoe's answer).
if (Keyboard.Modifiers == ModifierKeys.Shift && Keyboard.IsKeyDown(Key.Enter))
{
MessageBox.Show("test");
}
A good example can be found here.
public void TextBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
{
MessageBox.Show("Pressed " + Keys.Shift);
}
}

Capture key press in whole application

Is it possible, to capture (somewhere in app.xaml.cs i guess) any key and if it pressed open window?
Thanks for help!
There is a better way. Found this on a MS forum. Works like a charm.
Put this code in Application startup:
EventManager.RegisterClassHandler(typeof(Window),
Keyboard.KeyUpEvent,new KeyEventHandler(keyUp), true);
private void keyUp(object sender, KeyEventArgs e)
{
//Your code...
}
You could use something like this gist to register a global hook. It will fire whenever the given keys are pressed while your application is running. You can use it in your App class like this:
public partial class App
{
private HotKey _hotKey;
protected override void OnActivated(EventArgs e)
{
base.OnActivated(e);
RegisterHotKeys();
}
protected override void OnExit(ExitEventArgs e)
{
base.OnExit(e);
UnregisterHotKeys();
}
private void RegisterHotKeys()
{
if (_hotKey != null) return;
_hotKey = new HotKey(ModifierKeys.Control | ModifierKeys.Shift, Key.V, Current.MainWindow);
_hotKey.HotKeyPressed += OnHotKeyPressed;
}
private void UnregisterHotKeys()
{
if (_hotKey == null) return;
_hotKey.HotKeyPressed -= OnHotKeyPressed;
_hotKey.Dispose();
}
private void OnHotKeyPressed(HotKey hotKey)
{
// Do whatever you want to do here
}
}
Yes and no.
Focus plays a role in the order for which a given key is handled. The control which captures the initial key press can opt to not pass the key along, which would prohibit you from capturing it at the top most level. In addition there are controls within the .NET framework that swallow certain keys under certain scenarios, however I am unable to recall a specific instance.
If your application is small and the depth is nothing more than a Window with buttons, this is certainly attainable and would follow the standard approach to capturing key strokes within a WPF application.
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)
myVariable = true;
if (ctrl && e.Key == Key.S)
base.OnKeyDown(e);
}
protected override void OnKeyUp(KeyEventArgs e)
{
if (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)
myVariable = false;
base.OnKeyUp(e);
}
If your application is large you can attempt a global hook as detailed here but understand that the aforementioned caveats can still exist.

Fire button event manually

I have a search text box on my WPF Windows. Whenever, the user presses enter key after writing some query in the textBox, the process should start.
Now, I also have this Search button, in the event of which I perform all this process.
So, for a texBox:
<TextBox x:Name="textBox1" Text="Query here" FontSize="20" Padding="5" Width="580" KeyDown="textBox1_KeyDown"></TextBox>
private void queryText_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Return)
{
//how do I fire the button event from here?
}
}
It is possible but rather move your search logic into a method such as DoSearch and call it from both locations (text box and the search button).
Are you talking about manually invoking buttonSearch_onClick(this, null);?
You can Create a Common Method to do search for ex
public void MySearch()
{
//Logic
}
Then Call it for diffetnt places you want like...
private void queryText_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Return)
{
MySearch();
}
}
private void buttonSearch_onClick(object sender, EventArgs e)
{
MySearch();
}
A event can not be fired/raised from outside the class in which it is defined.(Using reflection you can definitely do that, but not a good practice.)
Having said that, you can always call the button click event handler from the code as simple method call like below
private void queryText_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Return)
{
OnSearchButtonClick(SearchButton, null);
}
}

C# Textbox Keypress Control Help

I have a standard textbox that I want to perform an action on a keypress. I have this code currently:
private void idTextEdit_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Enter/Return)
{
e.Handled = true;
SearchButtonClick(sender, EventArgs.Empty);
}
}
The problem is, I have tried both Enter and Return up there which is the reason for that. It is only firing that check for normal keys that are not like shift, control, etc. How can I design this so that it will pick up and use the enter/return key in the same way?
You should use the KeyDown event instead:
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Return)
{
//...
}
}
If it for some reason has to be KeyPress, you can use (char)13 or '\r' for your check, though I doubt that would work well on a non-Windows OS.
if (e.KeyChar == '\r')
You cannot just cast Keys.Return to a char, because it's a bitflag enum and doesn't just hold the corresponding ASCII code.
Use the KeyDown event instead.

Categories