【问题标题】:Change paste contents in Textbox更改文本框中的粘贴内容
【发布时间】:2011-09-30 21:25:55
【问题描述】:

如何动态更改将粘贴到 TextBox 中的内容。

这是我订阅活动的方式:

DataObject.AddPastingHandler (uiTextBox, TextBoxPaste);

这是我定义事件处理程序的方式:

private void TextBoxPaste (object sender, DataObjectPastingEventArgs args)
{
    string clipboard = args.DataObject.GetData (typeof (string)) as string;

    Regex nonNumeric = new System.Text.RegularExpressions.Regex (@"\D");
    string result = nonNumeric.Replace (clipboard, String.Empty);

    // I can't just do "args.DataObject.SetData (result)" here.
}

【问题讨论】:

    标签: c# .net wpf


    【解决方案1】:

    您不能调用 args.DataObject.SetData("some data") 因为 DataObject 已冻结。您可以做的是完全替换 DataObject:

    private void TextBoxPaste(object sender, DataObjectPastingEventArgs e) {
            string text = (String)e.DataObject.GetData(typeof(String));
            DataObject d = new DataObject();
            d.SetData(DataFormats.Text, text.Replace(Environment.NewLine, " "));
            e.DataObject = d;
     }
    

    【讨论】:

    • 这是一个更优雅的解决方案
    【解决方案2】:

    我可以想到两种方式,都不是很吸引人:) 两种方式都包括取消粘贴命令。

    第一种方法是取消粘贴命令,然后计算如果粘贴result 后文本的外观。

    private void TextBoxPaste(object sender, DataObjectPastingEventArgs args)
    {
        string clipboard = args.DataObject.GetData(typeof(string)) as string;
    
        Regex nonNumeric = new System.Text.RegularExpressions.Regex(@"\D");
        string result = nonNumeric.Replace(clipboard, String.Empty);
    
        int start = uiTextBox.SelectionStart;
        int length = uiTextBox.SelectionLength;
        int caret = uiTextBox.CaretIndex;
    
        string text = uiTextBox.Text.Substring(0, start);
        text += uiTextBox.Text.Substring(start + length);
    
        string newText = text.Substring(0, uiTextBox.CaretIndex) + result;
        newText += text.Substring(caret);
        uiTextBox.Text = newText;
        uiTextBox.CaretIndex = caret + result.Length;
    
        args.CancelCommand();
    }
    

    另一种方法是取消粘贴命令,更改剪贴板中的文本,然后重新执行粘贴。这还需要您区分真正的粘贴命令和手动调用的粘贴命令。像这样的

    bool m_modifiedPaste = false;
    private void TextBoxPaste(object sender, DataObjectPastingEventArgs args)
    {
        if (m_modifiedPaste == false)
        {
            m_modifiedPaste = true;
            string clipboard = args.DataObject.GetData(typeof(string)) as string;
    
            Regex nonNumeric = new System.Text.RegularExpressions.Regex(@"\D");
            string result = nonNumeric.Replace(clipboard, String.Empty);
    
            args.CancelCommand();
    
            Clipboard.SetData(DataFormats.Text, result);
            ApplicationCommands.Paste.Execute(result, uiTextBox);
        }
        else
        {
            m_modifiedPaste = false;
        }
    }
    

    【讨论】:

    • 是的,我也在按照您的第一种方法进行思考。第二种方法要差得多,因为您正在修改剪贴板内容。不管怎样,这正是我想要的,谢谢!
    • 感谢您的回答。我只想发布第一种方法的较短版本(从 9 行到 3 行):int caret = uiTextBox.CaretIndex; uiTextBox.Text = uiTextBox.Text.Insert(uiTextBox.SelectionStart, result); uiTextBox.CaretIndex = caret + result.Length;
    • Sender 是发生粘贴事件的文本框,因此您不必显式引用特定的文本框,只需将 sender 转换为 TextBox (或其他)。
    • @Farawin 关于完全替换 DataObject 的答案比这个公认的答案要优雅得多。
    【解决方案3】:

    我经常使用 VB.net,我已经测试过这个 C# 位,我使用了转换器,因为我很蹩脚:)

        string oClipboard;
    
        private void TextBox1_GotFocus(object sender, System.EventArgs e)
        {
            oClipboard = Clipboard.GetText();
            Clipboard.SetText("foo");
        }
    
        private void TextBox1_LostFocus(object sender, System.EventArgs e)
        {
            Clipboard.SetText(oClipboard);
        }
    

    当控件获得焦点时,我将剪贴板设置为新文本。它存储旧值。稍后,当控件失去焦点时,剪贴板被设置回旧值。

    【讨论】:

      【解决方案4】:

      只是对@Fredrik 的代码进行了一些修改,因为我一直在尝试他的两种方法。

      第一个只是缩短版

      private void TextBox_Pasting(object sender, DataObjectPastingEventArgs e)
      {
          string clipboard = e.DataObject.GetData(typeof(string)) as string;
          Regex nonNumeric = new System.Text.RegularExpressions.Regex (@"\D");
          string result = nonNumeric.Replace(clipboard, string.Empty);
      
          int caret = CaretIndex;
          Text = Text.Substring(0, SelectionStart) + result +
              Text.Substring(SelectionStart + SelectionLength);
          CaretIndex = caret + result.Length;
      
          e.CancelCommand();
      }
      

      另一个更新并保留剪贴板内容

      private string oldClipboardContent { get; set; } = "";
      private bool pasteModified { get; set; } = false;
      
      private void TextBox_Pasting(object sender, DataObjectPastingEventArgs e)
      {
          if (pasteModified)
          {
              pasteModified = false;
          }
          else
          {
              pasteModified = true;
      
              string text = (string)e.DataObject.GetData(typeof(string));
              oldClipboardContent = text;
      
              Regex nonNumeric = new System.Text.RegularExpressions.Regex (@"\D");
              text = nonNumeric.Replace(text, string.Empty);
              e.CancelCommand();
      
              Clipboard.SetData(DataFormats.Text, text);
              ApplicationCommands.Paste.Execute(text, this);
      
              Clipboard.SetData(DataFormats.Text, OldClipboardContent);
              oldClipboardContent = "";
          }
      }
      

      我在我的自定义 TextBox 控件中使用了这些,这就是为什么我可以在不先写名称的情况下访问 TextBox 属性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-01-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-12
        • 1970-01-01
        相关资源
        最近更新 更多