2011-09-30 23 views
17

¿Cómo puedo cambiar dinámicamente el contenido de lo que se pegará en el cuadro de texto?Cambiar contenido de pegado en el cuadro de texto

Así es como me suscribo al evento:

DataObject.AddPastingHandler (uiTextBox, TextBoxPaste); 

Aquí es cómo definir el controlador de eventos:

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

Respuesta

15

Puedo pensar de dos maneras, ninguna de las cuales es muy atractiva :) Y ambas formas incluyen cancelar el comando pegar.

La primera forma sería cancelar el comando pegar y luego calcular cómo se vería el texto después del pegado si se pegó result en su lugar.

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

La otra manera sería cancelar el comando pegar, cambiar el texto en el Portapapeles y luego volver a ejecutar Pegar. Esto también requeriría que difiera entre el comando de pegado real y el comando pegar invocado manualmente. Algo como esto

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

Sí, yo también estaba pensando en la línea de su primer método. El segundo método es considerablemente peor, ya que está modificando el contenido del Portapapeles. De cualquier manera, esto es exactamente lo que estaba buscando, ¡gracias! – Dave

+0

Gracias por la respuesta. Solo quiero publicar una versión más corta del primer método (de 9 líneas a 3 líneas): 'int caret = uiTextBox.CaretIndex; uiTextBox.Text = uiTextBox.Text.Insert (uiTextBox.SelectionStart, result); uiTextBox.CaretIndex = currículum + resultado.Length; ' – newman

+0

Remitente es el cuadro de texto en el que se produce el evento pegar, por lo que en lugar de tener que hacer referencia explícitamente a un cuadro de texto en particular, puede emitir el remitente como' TextBox' (o lo que sea) . – Will

0

utilizo VB.net un poco, he probado este C# bits, que utiliza un convertidor porque soy cojo :)

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

fijo el portapapeles en el nuevo texto cuando el control recibe el foco. Almacena el valor anterior. Más tarde, cuando el control pierde el foco, el portapapeles vuelve al valor anterior.

23

no se puede llamar args.DataObject.SetData ("algunos datos") ya que el DataObject se congela. Lo que puede hacer es sustituir el DataObject completo:

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

Esto de lejos es una solución más elegante –

0

Sólo algunas modificaciones del código de Fredrik @, ya que he estado probando ambos de sus métodos.

El primero es simplemente una versión abreviada

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

y el otro se actualiza manteniendo el contenido del portapapeles

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

yo estaba usando los que están dentro de mi control personalizado TextBox, es por eso que podría acceder a TextBox propiedades sin escribir el nombre primero.

Cuestiones relacionadas