Изменить содержимое вставки в текстовом поле

#c# #.net #wpf

#c# #.net #wpf

Вопрос:

Как я могу динамически изменять содержимое того, что будет вставлено в текстовое поле.

Вот как я подписываюсь на событие:

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

Ответ №1:

Вы не можете вызывать аргументы.Объект данных.setData(«некоторые данные»), поскольку объект 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;
 }
  

Комментарии:

1. Это, безусловно, более элегантное решение

Ответ №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)   resu<
    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;
    }
}
  

Комментарии:

1. Да, я тоже думал о вашем первом методе. Второй метод значительно хуже, поскольку вы изменяете содержимое буфера обмена. В любом случае, это именно то, что я искал, спасибо!

2. Спасибо за ответ. Я просто хочу опубликовать более короткую версию первого метода (от 9 строк до 3 строк): int caret = uiTextBox.CaretIndex; uiTextBox.Text = uiTextBox.Text.Insert(uiTextBox.SelectionStart, result); uiTextBox.CaretIndex = caret result.Length;

3. Sender — это текстовое поле, в котором происходит событие вставки, поэтому вместо того, чтобы явно ссылаться на конкретное текстовое поле, вы можете просто указать sender как TextBox (или что угодно).

4. Ответ @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 к свойствам, не вводя сначала имя.