我正在尝试拦截粘贴到 WPF 文本框中的数据。
例如,用户使用 Windows 截图工具创建屏幕截图,该工具会自动将图像数据放在剪贴板上。这里的想法是允许用户在 TextBox 上简单地按 CTRL+V,这样我就可以拦截它,检查它是否是数据,然后用它做任何我想做的事情。
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);
}
}
使用上面的行为,当文本粘贴到 TextBox 时,代码确实会被触发,但似乎 TextBox 不允许粘贴任何其他内容,因此如果不是文本,它甚至永远不会到达此代码。
我想知道,是否需要在 TextBox 上设置一个属性,或者其他允许粘贴数据的属性(即使 TextBox 永远无法显示该数据)
如果没有,哪些 UI 元素确实允许粘贴数据,因为我也可以利用它来发挥我的优势。
更新
有人向我发帖说我必须使用 RichTextBox 来允许
像这样粘贴,这不是我可以使用的,所以我决定采用不同的(有点 hacky)方法:
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();
}
}
}
这允许我将图像和文件粘贴到文本框中,但只能使用 CTRL+V 键,而不是使用文本框的默认上下文菜单。
所以我仍然有兴趣知道是否有更好/更简单的方法
更新 2 基于 Daniel 的解决方案,效果非常好,我更新了 OnAttached:
protected override void OnAttached()
{
base.OnAttached();
CommandManager.AddPreviewCanExecuteHandler(AssociatedObject, onPreviewCanExecute);
CommandManager.AddPreviewExecutedHandler(AssociatedObject, onPreviewExecuted);
}
并删除了 PreviewKeyDownHandler。