I am trying to intercept data inserted into a WPF text box.
For example, a user creates a screen capture using the Windows shutdown tool, which automatically puts image data on the clipboard. The idea here is to allow the user to simply CTRL + V in the TextBox so that I can intercept it, check, and then do whatever I want with it.
public class PasteBehavior : Behavior<UIElement> { protected override void OnAttached() { base.OnAttached(); DataObject.AddPastingHandler(AssociatedObject, new DataObjectPastingEventHandler(OnPaste)); } protected override void OnDetaching() { base.OnDetaching(); } private void OnPaste(object sender, DataObjectPastingEventArgs e) { if (e.SourceDataObject.GetDataPresent(DataFormats.Text)) return; var formats = e.SourceDataObject.GetFormats(); foreach (var format in formats) Console.WriteLine(format); } }
Using the above behavior, the code runs when the text is inserted into the TextBox, but it would seem that the TextBox does not allow you to insert anything else so that it never reaches this code if it is not text.
I am wondering if there is a property that needs to be set in a TextBox or something else that will allow data to be inserted (although a TextBox can never display this data)
If not, what user interface elements allow you to insert data, since I could use it to my advantage.
Update Someone sent me a message that I would have to use RichTextBox to allow embedding
for example, this is not something I can use, so I decided to take a different (somewhat hacked) approach:
public class PasteBehavior : Behavior<UIElement> { protected override void OnAttached() { base.OnAttached(); AssociatedObject.PreviewKeyDown += AssociatedObject_PreviewKeyDown; } void AssociatedObject_PreviewKeyDown(object sender, KeyEventArgs e) { if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.V) { if (Clipboard.ContainsData(DataFormats.Dib)) { using (var stream = new MemoryStream()) { var image = Clipboard.GetImage(); var message = new ImagePastedMessage() { ImageData = GetImagePngData(image) }; Messenger.Default.Send(message); } e.Handled = true; } else if (Clipboard.ContainsFileDropList()) { var results = Clipboard.GetFileDropList(); var filenames = new string[results.Count]; results.CopyTo(filenames, 0); var message = new FilesDroppedMessage() { Filenames = filenames }; Messenger.Default.Send(message); e.Handled = true; } } } protected override void OnDetaching() { base.OnDetaching(); } private byte[] GetImagePngData(BitmapSource source) { using (var stream = new MemoryStream()) { var encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(source)); encoder.Save(stream); return stream.ToArray(); } } }
This allows me to embed images and files in a TextBox, but only using the CTRL + V keys, not using the default context menu for the TextBox.
So I'm still curious to know if there is a better / easier way
Update 2 Based on Daniel's solution, which works very well, I updated OnAttached:
protected override void OnAttached() { base.OnAttached(); CommandManager.AddPreviewCanExecuteHandler(AssociatedObject, onPreviewCanExecute); CommandManager.AddPreviewExecutedHandler(AssociatedObject, onPreviewExecuted); }
And deleted PreviewKeyDownHandler.