我创建了一个继承TextBox
的自定义控件。此自定义控件是数字TextBox
,仅支持数字。
我正在使用OnPreviewTextInput
检查每个要输入的新字符,以查看该字符是否为有效输入。这非常有效。但是,如果我将文字粘贴到TextBox
,则不会触发OnPreviewTextInput
。
在TextBox
中捕获粘贴文本的最佳方法是什么?
另外,我在按下后退空间时遇到问题,我无法弄清楚这会触发什么事件。 OnPreviewTextInput
未被解雇!
如何在WPF TextBox
中捕获粘贴的文本和后台空间事件?
答案 0 :(得分:114)
以下是我曾经需要的一些代码。可以帮到你。
public Window1()
{
InitializeComponent();
// "tb" is a TextBox
DataObject.AddPastingHandler(tb, OnPaste);
}
private void OnPaste(object sender, DataObjectPastingEventArgs e)
{
var isText = e.SourceDataObject.GetDataPresent(DataFormats.UnicodeText, true);
if (!isText) return;
var text = e.SourceDataObject.GetData(DataFormats.UnicodeText) as string;
...
}
答案 1 :(得分:14)
尝试拦截和捕获可能导致TextBox.Text属性更改的所有单个事件的麻烦是有很多这样的事件:
试图可靠地拦截所有这些是徒劳的。一个更好的解决方案是监视TextBox.TextChanged并拒绝您不喜欢的更改。
在this answer中,我展示了如何为所询问的特定场景实现TextBoxRestriction类。同样的技术可以推广用于您想要放置在TextBox控件上的任何限制。
例如,在您的情况下,您可以实现RestrictValidChars
附加属性,类似于该代码中的RestrictDeleteTo
属性。它将是相同的,除了内循环将检查插入,而不是删除。它会像这样使用:
<TextBox my:TextBoxRestriction.RestrictValidChars="0123456789" />
这只是一个如何处理它的想法。根据您的需要,有许多方法可以构建代码。例如,您可以更改TextBoxRestriction以调用您自己的代码,以使用附加属性进行验证,该属性接受委托或包含事件的对象。
有关如何在使用TextBoxRestriction类时绑定Text属性的详细信息,请参阅另一个答案,以便在您不希望它时不会触发限制。
答案 2 :(得分:7)
对于退格键,请查看PreviewKeyDown事件
对于paste命令,添加命令绑定到ApplicationCommands.Paste,如果你不想对它执行任何操作,请将参数设置为handle:
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Paste"
Executed="PasteExecuted" />
</Window.CommandBindings>
在代码背后:
private void PasteExecuted(object sender, ExecutedRoutedEventArgs e)
{
e.Handled = true;
}
答案 3 :(得分:2)
您可以使用PreviewKeyDown
事件和TextChanged
事件来实现此目的。
在PreviewKeyDown
中捕获粘贴操作
if(Key.V == e.Key && Keyboard.Modifiers == ModifierKeys.Control)
{
strPreviousString = this.txtNumber.Text;
bIsPasteOperation = true;
}
在TextChanged
事件中
if (true == bIsPasteOperation)
{
if (false == this.IsNumber(this.txtNumber.Text))
{
this.txtNumber.Text = strPreviousString;
e.Handled = true;
}
bIsPasteOperation = false;
}
IsNumber
方法验证输入的文本是否为数字
private bool IsNumber(string text)
{
int number;
//Allowing only numbers
if (!(int.TryParse(text, out number)))
{
return false;
}
return true
}
答案 4 :(得分:0)
这对我很好。当用户更改内容时,我想更改文本框的颜色。
我能够通过以下3个事件实现这一目标:
public bool IsDirty {
set {
if(value) {
txtValue.Background = Brushes.LightBlue;
} else {
txtValue.Background = IsReadOnly ? Brushes.White : Brushes.LightYellow;
}
}
get {
return txtValue.Background == Brushes.LightBlue;
}
}
private void PreviewTextInput(object sender, TextCompositionEventArgs e) {
TextBox tb = ((TextBox)sender);
string originalText = tb.Text;
string newVal = "";
//handle negative
if (e.Text=="-") {
if(originalText.IndexOf("-") > -1 || tb.CaretIndex != 0 || originalText == "" || originalText == "0") {
//already has a negative or the caret is not at the front where the - should go
//then ignore the entry
e.Handled = true;
return;
}
//put it at the front
newVal = e.Text + originalText;
} else {
//normal typed number
newVal = originalText + e.Text;
}
//check if it's a valid double if so then dirty
double dVal;
e.Handled = !double.TryParse(newVal, out dVal);
if(!e.Handled) {
IsDirty = true;
}
}
private void PreviewKeyUp(object sender, KeyEventArgs e) {
//handle paste
if ((Key.V == e.Key || Key.X == e.Key) && Keyboard.Modifiers == ModifierKeys.Control) {
IsDirty = true;
}
//handle delete and backspace
if (e.Key == Key.Delete || e.Key == Key.Back) {
IsDirty = true;
}
}
private void PreviewExecuted(object sender, ExecutedRoutedEventArgs e) {
//handle context menu cut/paste
if (e.Command == ApplicationCommands.Cut || e.Command == ApplicationCommands.Paste) {
IsDirty = true;
}
}
答案 5 :(得分:0)
这可能不是您要找的确切答案,但是这是如何处理粘贴的文本(如果用户使用上下文菜单粘贴,这也适用):
const storeAuth = {
forgotPassword: jest.fn(() => Promise.resolve({ data: {} })),
}
const middleWare = [thunk.withExtraArgument(storeAuth)]
const mockStore = configureStore(middleWare)
要处理退格,请使用PreviewKeyDown事件。
答案 6 :(得分:0)
以下代码对我有用。我希望这会对某人有所帮助。
如果使用的是Xceed RichTextBox控件,请使用以下代码。
<xctk:RichTextBox Name="Description" CommandManager.PreviewExecuted="CommandExecuted_PreviewExecuted">
private void CommandExecuted_PreviewExecuted(object sender, RoutedEventArgs e)
{
Xceed.Wpf.Toolkit.RichTextBox richTextBox = (Xceed.Wpf.Toolkit.RichTextBox)sender;
string rtbtext = StringFromRichTextBox(richTextBox);
if ((e as ExecutedRoutedEventArgs).Command == ApplicationCommands.Paste)
{
// verify that the textbox handled the paste command
if (Clipboard.GetText() > 2500)//Get copied text from clipboard
{
e.Handled = true;// prevent paste if length is more than 2500.
return;
}
}
}
如果您使用的是TextBlock,请使用以下代码
TextBlock textBlock = (TextBlock)sender;
代替此
Xceed.Wpf.Toolkit.RichTextBox richTextBox = (Xceed.Wpf.Toolkit.RichTextBox)sender;
其余所有代码也可以保持与TextBlock相同。