开发者

Change paste contents in Textbox

开发者 https://www.devze.com 2023-04-09 11:11 出处:网络
How can I dynamically change the contents of what will be pasted in the TextBox. Here is how I subscribe to the event:

How can I dynamically change the contents of what will be pasted in the TextBox.

Here is how I subscribe to the event:

DataObject.AddPastingHandler (uiTextBox, TextBoxPaste);

Here is how I define the event handler:

private void TextBoxPaste (object sender, DataObje开发者_如何学PythonctPastingEventArgs 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.
}


You cannot call args.DataObject.SetData("some data") since the DataObject is frozen. What you can do is replace the DataObject altogether:

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;
 }


I can think of two ways, none of which are very attractive :) And both ways include canceling the paste command.

The first way would be to cancel the paste command and then calculate what the text would look like after the paste if result was pasted instead.

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();
}

The other way would be to cancel the paste command, change the text in the Clipboard and then re-execute paste. This would also require you to differ between the real paste command and the manually invoked paste command. Something like this

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;
    }
}


I use VB.net quite a bit, I've tested this C# bit, I used a converter because I'm lame :)

    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);
    }

I set the clipboard to the new text when the control gets focus. It stores the old value. Later, when the control loses focus, the clipboard is set back to the old value.


Just some modifications of @Fredrik's code, since I've been trying out both of his methods.

First one is just a shortened version

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();
}

and the other one is updated with keeping the clipboard content

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 = "";
    }
}

I was using those inside my custom TextBox control, that is why I could access TextBox properties without writing the name first.

0

精彩评论

暂无评论...
验证码 换一张
取 消