2012-06-20 11 views
7

टेक्स्टबॉक्स का उपयोग करते समय पूर्ववत करने में असमर्थ .Undo(); मैं निम्नलिखित त्रुटि मिलती है:TextChanged

Cannot Undo or Redo while undo unit is open.

अब मैं समझता हूँ क्यों यह मामला है (क्योंकि यह एक सक्रिय पूर्ववत करने योग्य घटना है), लेकिन के माध्यम से क्या घटना मैं एक पाठ बॉक्स पर सत्यापन करने और परिवर्तन को पूर्ववत् उपयोगकर्ता है, तो कर सकते हैं एक अवैध चरित्र टाइप किया?

+0

आपको इसके बजाय व्यवहार का उपयोग करना चाहिए। – SepehrM

+0

सेपेरम - क्या आप एक उदाहरण प्रदान कर सकते हैं? क्या होगा यदि आप अभी तक मान्य नहीं करना चाहते हैं, लेकिन बस अपने सत्र को उड़ाने से इस अपवाद संदेश को रोकना चाहते हैं? मुझे यह मिल रहा है जब कोई उपयोगकर्ता बहुत तेज़ी से टाइप करता है या शायद फ़ील्ड में डेटा का एक हिस्सा चिपकाता है। मान्य भी नहीं है। – Allen

उत्तर

6

पूर्ववत और टेक्स्ट चेंज किए जाने के बजाय, आपको PreviewTextInput और DataObject.Pasting ईवेंट का उपयोग करना चाहिए। PreviewTextInput इवेंट हैंडलर में, e.Handled को सत्य पर सेट करें यदि टाइप किया गया टेक्स्ट एक अमान्य चरित्र है। Pasting इवेंट हैंडलर में, चिपका हुआ टेक्स्ट अमान्य है, तो e.CancelCommand() पर कॉल करें।

यहाँ कि स्वीकार करता है एक पाठ बॉक्स के लिए एक उदाहरण है कि आप केवल संख्याएँ 0 और 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> 

कोड के पीछे:

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

शानदार - सही समाधान धन्यवाद –

+0

ग्रेट, "पेस्टिंग" हैंडलर यह भी मान्य करता है कि क्या आप ड्रैग और ड्रॉप का उपयोग कर वर्ण डाल रहे हैं। – Mishax

+0

इस दृष्टिकोण के साथ समस्या यह है कि previewTextInput केवल जो भी टाइप किया जा रहा है उसका पूर्वावलोकन करता है, न कि अंतिम परिणाम।यह केवल तभी काम कर सकता है जब कोई मान्य मूल्य के संबंध में सभी संभावित इनपुट के लिए एक बहुत ही जटिल और अनजान एल्गोरिदम लिखता है। उदाहरण के लिए, दशमलव फ़ील्ड पर, शून्य या अवधि लागू होने पर मान्य करने का प्रयास करें। जाहिर है, आप केवल प्रत्येक में से 1 टाइप कर सकते हैं, लेकिन हर जगह में नहीं। सबसे अच्छा समाधान अंतिम परिणाम को सत्यापित करना है, _regardless_ इसे टाइप किया गया था। दुर्भाग्यवश, डब्ल्यूपीएफ के पास समर्थन नहीं है। – Neolisk

3

कॉल से पूर्ववत एसिंक्रोनस रूप से टेक्स्ट चेंजेड इवेंट हैंडलर से:

Dispatcher.BeginInvoke(new Action(() => tb.Undo())) 
+0

यह समाधान स्वीकृत उत्तर के विरुद्ध तुलना कैसे करता है? – InvalidBrainException

7

सिम्बे के दृष्टिकोण का उत्तर देने के लिए, जो मुझे लगता है कि इसे खारिज कर दिया जा रहा है।

आप टेक्स्ट चेंज में पूर्ववत नहीं कह सकते हैं क्योंकि पूर्ववत ऑपरेशन अभी भी टेक्स्टबॉक्स द्वारा तैयार किया जा रहा है। ऐसा लगता है कि कभी-कभी काम नहीं होता है और दूसरी बार नहीं, इसलिए यह सुझाव देता है कि घटना के संकेत के दौरान दौड़ की स्थिति और पूर्ववत तैयारी के पूरा होने के बीच दौड़ की स्थिति है।

हालांकि डिस्पैचर पर लगाए गए अंडो को कॉल करने से टेक्स्ट बॉक्स को पूर्ववत तैयारी पूरी करने की अनुमति मिल जाएगी। आप टेक्स्ट परिवर्तन के परिणामों को प्रमाणित कर सकते हैं और फिर यह तय कर सकते हैं कि आप परिवर्तन को रखना या पूर्ववत करना चाहते हैं या नहीं। यह सबसे अच्छा तरीका नहीं हो सकता है, लेकिन मैंने कोशिश की और टेक्स्ट बॉक्स में पाठ परिवर्तनों और पेस्टों का एक गुच्छा विस्फोट किया और अपवाद को पुन: उत्पन्न नहीं कर सका।

"स्वीकृत उत्तर" केवल तभी महान होता है जब आप किसी अमान्य चरित्र को दर्ज या पेस्ट करने से रोकना चाहते हैं, लेकिन आम तौर पर मैं अक्सर टेक्स्टबॉक्स इनपुट की बहुत अधिक शामिल सत्यापन करता हूं और अंतिम टेक्स्ट मान सत्यापित करना चाहता हूं। पूर्वावलोकन ईवेंट से अंतिम पाठ को समझना आसान नहीं है क्योंकि जहां तक ​​नियंत्रण का संबंध है, अभी तक कुछ भी नहीं हुआ है।

टेरिबैड के प्रश्न का उत्तर देने के लिए, सिंबे का उत्तर बेहतर और अधिक परिस्थितियों में अधिक संक्षिप्त है।

tb.TextChanged =+ (sender, args) => 
{ 
    if(! MeetsMyExpectations(tb.Text)) 
     Dispatcher.BeginInvoke(new Action(() => tb.Undo())); 
} 

मैंने टेक्स्ट बॉक्स सत्यापन में बहुत सारे जंगली रोमांच पढ़े हैं और यह जितना आसान है उतना आसान है।

संबंधित मुद्दे

 संबंधित मुद्दे