c#-在WPF文本框中粘贴事件

我创建了一个自定义控件,继承了TextBox。此自定义控件是一个数字TextBox,仅支持数字。

我正在使用TextBox检查正在键入的每个新字符,以查看该字符是否为有效输入。 这很好。 但是,如果我将文本粘贴到TextBox中,则不会触发OnPreviewTextInput

TextBox中捕获粘贴文本的最佳方法是什么?

另外,按退格键时我有一个问题,我无法弄清楚会触发什么事件。 TextBox未触发!

有什么想法如何在WPF TextBox中捕获粘贴的文本和退格事件吗?

code-zoop asked 2019-10-09T16:48:59Z
5个解决方案
112 votes

这是我需要的一些代码。 可能会帮助您。

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;
    ...
}
Matt Hamilton answered 2019-10-09T16:49:12Z
14 votes

尝试拦截和捕获可能导致TextBox.Text属性更改的所有单个事件的麻烦在于,存在许多此类事件:

  • TextInput:用户类型
  • KeyDown:删除,退格,Enter,IME
  • 命令手势:Ctrl-X,Ctrl-Y,Ctrl-V,Ctrl-X
  • MouseDown:粘贴按钮,剪切按钮,撤消按钮,...
  • 单击:当粘贴,剪切,撤消按钮具有本地焦点时按下空格键
  • RaiseEvent:代码引发粘贴,剪切,撤消,重做命令
  • 辅助功能:语音命令,盲文键盘等

试图可靠地拦截所有这些都是徒劳的。 更好的解决方案是监视TextBox.TextChanged并拒绝您不喜欢的更改。

在此答案中,我将说明如何针对所询问的特定方案实现TextBoxRestriction类。 可以将这种相同的技术推广到要在TextBox控件上放置的任何限制。

例如,在您的情况下,您可能会暗示RestrictValidChars附加属性,类似于该代码中的RestrictDeleteTo属性。 除了内部循环将检查插入而不是删除之外,这将是相同的。 它的用法如下:

<TextBox my:TextBoxRestriction.RestrictValidChars="0123456789" />

这只是如何处理的一个想法。 有许多方法可以根据您的需要来构造代码。 例如,您可以更改TextBoxRestriction以调用您自己的代码,以使用带有委托或包含事件的对象的附加属性进行验证。

有关使用TextBoxRestriction类时如何绑定Text属性的详细信息,请参见其他答案,这样当您不希望使用该属性时就不会触发该限制。

Ray Burns answered 2019-10-09T16:51:17Z
7 votes

对于退格键,请检查PreviewKeyDown事件

对于粘贴命令,如果您不想对其进行任何操作,则将命令绑定添加到ApplicationCommands.Paste,并将参数设置为handled:

<Window.CommandBindings>
  <CommandBinding Command="ApplicationCommands.Paste"
                  Executed="PasteExecuted" />
</Window.CommandBindings>

并在后面的代码中:

private void PasteExecuted(object sender, ExecutedRoutedEventArgs e)
{
    e.Handled = true;
}
Arcturus answered 2019-10-09T16:52:01Z
2 votes

您可以通过IsNumber事件和TextChanged事件来实现。

IsNumber中捕获粘贴操作

if(Key.V == e.Key && Keyboard.Modifiers == ModifierKeys.Control)
{
   strPreviousString = this.txtNumber.Text;
   bIsPasteOperation = true;
}

IsNumber事件

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
}
Syed answered 2019-10-09T16:52:49Z
0 votes

这对我来说很好。 当用户更改内容时,我想更改文本框的颜色。

  • 接受数字,包括句号和负字符
  • 输入的键:删除,退格键,Ctrl-V(粘贴),Ctrl-X(剪切)
  • 右键单击以粘贴并剪切

我通过以下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;
        }
    }
JJ_Coder4Hire answered 2019-10-09T16:53:44Z
translate from https://stackoverflow.com:/questions/3061475/paste-event-in-a-wpf-textbox