2012-06-20 16 views
7

Bei Verwendung von textbox.Undo(); Ich erhalte die folgende Fehlermeldung:Rückgängig in TextChanged kann nicht verwendet werden

Cannot Undo or Redo while undo unit is open.

Jetzt verstehe ich, warum dies der Fall ist (weil es ein aktives undoable Ereignis ist), sondern durch das, was Ereignis kann ich Validierung auf einem Textfeld durchführen und die Änderung rückgängig zu machen, wenn der Benutzer ein ungültiges Zeichen eingegeben?

+0

Sie sollten stattdessen Verhaltensweisen verwenden. – SepehrM

+0

SepehrM - könnten Sie ein Beispiel geben? Was ist, wenn Sie noch nicht validieren wollen, aber diese verdammte Ausnahmebotschaft einfach davon abhalten wollen, Ihre Sitzung in die Luft zu jagen? Ich bekomme das, wenn ein Benutzer ein kleines Bit zu schnell eingibt oder ein Stück Daten in das Feld einfügt. Nicht einmal bestätigen. – Allen

Antwort

6

Anstatt Rückgängig und TextChanged zu verwenden, sollten Sie die Ereignisse PreviewTextInput und DataObject.Pasting verwenden. Setzen Sie im Ereignishandler PreviewTextInpute.Handled auf True, wenn der eingegebene Text ein ungültiges Zeichen ist. Rufen Sie im Ereignishandler Pastinge.CancelCommand() auf, wenn der eingefügte Text ungültig ist. Hier

ist ein Beispiel für ein Textfeld, das nur die Ziffern akzeptiert 0 und 1:

XAML:

<Window x:Class="BinaryTextBox.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="133" Width="329"> 
    <StackPanel> 
     <TextBox x:Name="txtBinary" Width="100" Height="24" 
       PreviewTextInput="txtBinary_PreviewTextInput" 
       DataObject.Pasting="txtBinary_Pasting"/> 
    </StackPanel> 
</Window> 

-Code hinter:

using System.Text.RegularExpressions; 
using System.Windows; 
using System.Windows.Input; 

namespace BinaryTextBox 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     private void txtBinary_PreviewTextInput(object sender, 
       TextCompositionEventArgs e) 
     { 
      e.Handled = e.Text != "0" && e.Text != "1"; 
     } 

     private void txtBinary_Pasting(object sender, DataObjectPastingEventArgs e) 
     { 
      if (!Regex.IsMatch(e.DataObject.GetData(typeof(string)).ToString(), "^[01]+$")) 
      { 
       e.CancelCommand(); 
      } 
     } 
    } 
} 
+0

Brilliant - perfekte Lösung danke –

+0

Großartig, der "Einfügen" -Handler validiert auch, wenn Sie Zeichen per Drag & Drop einfügen. – Mishax

+0

Problem bei diesem Ansatz ist, dass PreviewTextInput nur Vorschau zeigt, was immer getippt wird, und nicht das Endergebnis.Dies kann nur funktionieren, wenn man einen sehr komplizierten und nicht wartbaren Algorithmus schreibt, um alle möglichen Eingaben bezüglich eines gültigen Wertes zu berücksichtigen. Versuchen Sie beispielsweise in einem Dezimalfeld, zu validieren, wenn ein Minus oder eine Periode anwendbar ist. Natürlich können Sie nur 1 von jedem eingeben, aber nicht an jeder Stelle. Die beste Lösung ist die Validierung des Endergebnisses, unabhängig davon, wie es eingegeben wurde. WPF hat leider keine Unterstützung dafür. – Neolisk

3

Rufen Sie die Undo asynchron von der Von der TextChanged-Ereignisbehandlungsroutine:

+0

Wie vergleicht sich diese Lösung mit der akzeptierten Antwort? – InvalidBrainException

7

Antwort auf Simbay Ansatz, der meiner Meinung nach abgewiesen wird.

Sie können in TextChanged nicht Rückgängig aufrufen, da die Rückgängig-Operation noch von der TextBox vorbereitet wird. Es scheint manchmal zu funktionieren und nicht zu anderen Zeiten, also deutet dies darauf hin, dass zwischen dem Zeitpunkt der Signalisierung des Ereignisses und dem Abschluss der Rückgängig-Vorbereitung eine Wettlaufsituation besteht.

Durch Aufrufen von Undo, das auf dem Dispatcher aufgerufen wird, kann das Textfeld jedoch die Vorbereitungsbearbeitung rückgängig machen. Sie können die Ergebnisse der Textänderung validieren und dann entscheiden, ob Sie die Änderung beibehalten oder rückgängig machen möchten. Dies ist vielleicht nicht der beste Ansatz, aber ich habe es versucht und eine Reihe von Textänderungen in die Textbox eingefügt und konnte die Ausnahme nicht reproduzieren. Die "akzeptierte Antwort" ist NUR dann hilfreich, wenn Sie verhindern wollen, dass ein ungültiges Zeichen eingegeben oder eingefügt wird, aber im Allgemeinen mache ich oft eine wesentlich umfangreichere Validierung der TextBox-Eingabe und möchte den endgültigen Textwert überprüfen. Es ist nicht einfach, den endgültigen Text eines Preview-Ereignisses zu erkennen, da bis jetzt noch nichts passiert ist.

Um Terribads Frage zu beantworten, ist simbay's Antwort in mehr Situationen besser und prägnanter.

Ich habe viele wilde Abenteuer in Textbox-Validierung gelesen und das ist ungefähr so ​​einfach wie ich gefunden habe.

Verwandte Themen