2017-08-01 18 views
5

मेरे पास WPF में TextBox है। मैं TextBox में टेक्स्ट की लंबाई को प्रतिबंधित करना चाहता हूं। संपत्ति MaxLength द्वारा वर्णों की संख्या को प्रतिबंधित करने का एक आसान तरीका है।टेक्स्टबॉक्स में टेक्स्ट की बाधा लंबाई इसकी एन्कोडेड प्रस्तुति

मेरे उपयोग के मामले में मुझे अक्षरों की संख्या से पाठ को प्रतिबंधित करने की आवश्यकता नहीं है, लेकिन दिए गए एन्कोडिंग में पाठ के बाइनरी प्रतिनिधित्व की लंबाई तक। चूंकि कार्यक्रम जर्मनों द्वारा उपयोग किया जाता है, वहां कुछ उमलॉट होते हैं, जो दो बाइट का उपभोग करते हैं।

मैं पहले से ही एक विधि है, कि चेक, एक दिया स्ट्रिंग दिया लंबाई में फिट बैठता है, तो:,

public bool IsInLength(string text, int maxLength, Encoding encoding) 
{ 
    return encoding.GetByteCount(text) < maxLength; 
} 

किसी को भी एक विचार है कि कैसे एक तरह से पाठ बॉक्स को यह समारोह टाई है क्या उपयोगकर्ता है कि अधिकतम बाइट लंबाई से अधिक होने के लिए बहुत अधिक वर्ण दर्ज करने की कोई संभावना नहीं है।

इवेंट हैंडलर के बिना समाधान टेक्स्टबॉक्स के रूप में पेश किए जाते हैं DataTemplate के अंदर है।

+0

क्या आप डेटा प्रमाणीकरण और सत्यापन इंटरफ़ेस (Inotfiy ...) इनपुट का सत्यापन करने के लिए उपयोग करते हैं? – Jehof

+0

हाँ, मैं करता हूं। क्या तब कोई रास्ता है? – scher

+0

टेक्स्टबॉक्स – Jehof

उत्तर

3

ValidationRule बिल यहां फिट बैठ सकता है।

public sealed class ByteCountValidationRule : ValidationRule 
{ 
    // For this example I test using an emoji() which will take 2 bytes and fail this rule. 
    static readonly int MaxByteCount = 1; 

    static readonly ValidationResult ByteCountExceededResult = new ValidationResult(false, $"Byte count exceeds the maximum allowed limit of {MaxByteCount}"); 

    public override ValidationResult Validate(object value, CultureInfo cultureInfo) 
    { 
     var val = value as string; 

     return val != null && Encoding.UTF8.GetByteCount(val) > MaxByteCount 
      ? ByteCountExceededResult 
      : ValidationResult.ValidResult; 
    } 
} 

और XAML उपयोग:

<TextBox.Text> 
     <Binding Path="Text" UpdateSourceTrigger="PropertyChanged"> 
      <Binding.ValidationRules> 
       <local:ByteCountValidationRule /> 
      </Binding.ValidationRules> 
     </Binding> 
    </TextBox.Text> 

अब आप या तो 1 या 2 इमोजी ASCII वर्ण डाल सकते हैं विफलता को गति प्रदान करने के लिए (के बाद से या तो 1 बाइट सीमा पार हो जाएगी) यहाँ एक उदाहरण दिया गया है।

+0

पर निर्भर करता है। यह एक अच्छा समाधान है। ValidationRule का उपयोग करने के लिए मेरे लिए नया था और आगे के अनुप्रयोगों में मेरी मदद करेगा। हालांकि मैं एक समाधान की तलाश में था, जहां उपयोगकर्ता बहुत अधिक अक्षर इनपुट करने में सक्षम नहीं है। प्रमाणीकरण नियम के साथ उपयोगकर्ता बहुत अधिक अक्षर इनपुट करने में सक्षम है लेकिन एक त्रुटि प्राप्त करता है। – scher

+0

मुझे दृढ़ता से संदेह है कि आप देशी टेक्स्टबॉक्स का उपयोग करके इसे प्राप्त कर सकते हैं। उपयोगकर्ता वर्णों को दृष्टि से इनपुट कर सकता है लेकिन आपके व्यूमोडल्स को अमान्य जानकारी के साथ अद्यतन नहीं किया जाता है। यह ठीक है कि सिस्टम कैसे काम करता है। एक वर्कअराउंड अधिकतम लम्बाई के लिए बाध्यकारी जोड़ना होगा जो कि उपयोगकर्ता प्रकारों के रूप में इनपुट किए जा सकने वाले वर्णों की संख्या को गतिशील रूप से कम कर देता है, फिर भी यह भ्रमित उपयोगकर्ता अनुभव होने के अलावा 100% वांछित परिणाम प्राप्त करने में असफल हो जाता है। मैं दृढ़ता से सुझाव देता हूं कि नियंत्रण के डिफ़ॉल्ट अपेक्षित व्यवहार को बदलने के इस मार्ग को न छोड़ें। – Maverik

+0

मैं एक ['व्यवहार '] (https://msdn.microsoft.com/en-us/library/system.windows.interactivity.behavior (v = expression.40) के साथ समाधान पर काम कर रहा हूं।aspx)। यदि संभव हो तो मैं इसे पोस्ट करूंगा। – scher

-2

मैंने बहुत लंबे ग्रंथों के इनपुट को रोकने के लिए Alex Klaus का समाधान बढ़ाया है।

public class TextBoxMaxLengthBehavior : Behavior<TextBox> 
{ 
    public static readonly DependencyProperty MaxLengthProperty = 
     DependencyProperty.Register(
      nameof(MaxLength), 
      typeof(int), 
      typeof(TextBoxMaxLengthBehavior), 
      new FrameworkPropertyMetadata(0)); 

    public int MaxLength 
    { 
     get { return (int) GetValue(MaxLengthProperty); } 
     set { SetValue(MaxLengthProperty, value); } 
    } 

    public static readonly DependencyProperty LengthEncodingProperty = 
     DependencyProperty.Register(
      nameof(LengthEncoding), 
      typeof(Encoding), 
      typeof(TextBoxMaxLengthBehavior), 
      new FrameworkPropertyMetadata(Encoding.Default)); 

    public Encoding LengthEncoding 
    { 
     get { return (Encoding) GetValue(LengthEncodingProperty); } 
     set { SetValue(LengthEncodingProperty, value); } 
    } 

    protected override void OnAttached() 
    { 
     base.OnAttached(); 

     AssociatedObject.PreviewTextInput += PreviewTextInputHandler; 
     DataObject.AddPastingHandler(AssociatedObject, PastingHandler); 
    } 

    protected override void OnDetaching() 
    { 
     base.OnDetaching(); 

     AssociatedObject.PreviewTextInput -= PreviewTextInputHandler; 
     DataObject.RemovePastingHandler(AssociatedObject, PastingHandler); 
    } 

    private void PreviewTextInputHandler(object sender, TextCompositionEventArgs e) 
    { 
     string text; 
     if (AssociatedObject.Text.Length < AssociatedObject.CaretIndex) 
      text = AssociatedObject.Text; 
     else 
     { 
      // Remaining text after removing selected text. 
      string remainingTextAfterRemoveSelection; 

      text = TreatSelectedText(out remainingTextAfterRemoveSelection) 
       ? remainingTextAfterRemoveSelection.Insert(AssociatedObject.SelectionStart, e.Text) 
       : AssociatedObject.Text.Insert(AssociatedObject.CaretIndex, e.Text); 
     } 

     e.Handled = !ValidateText(text); 
    } 

    private bool TreatSelectedText(out string text) 
    { 
     text = null; 
     if (AssociatedObject.SelectionLength <= 0) 
      return false; 

     var length = AssociatedObject.Text.Length; 
     if (AssociatedObject.SelectionStart >= length) 
      return true; 

     if (AssociatedObject.SelectionStart + AssociatedObject.SelectionLength >= length) 
      AssociatedObject.SelectionLength = length - AssociatedObject.SelectionStart; 

     text = AssociatedObject.Text.Remove(AssociatedObject.SelectionStart, AssociatedObject.SelectionLength); 
     return true; 
    } 

    private void PastingHandler(object sender, DataObjectPastingEventArgs e) 
    { 
     if (e.DataObject.GetDataPresent(DataFormats.Text)) 
     { 
      var pastedText = Convert.ToString(e.DataObject.GetData(DataFormats.Text)); 
      var text = ModifyTextToFit(pastedText); 

      if (!ValidateText(text)) 
       e.CancelCommand(); 
      else if (text != pastedText) 
       e.DataObject.SetData(DataFormats.Text, text); 

     } 
     else 
      e.CancelCommand(); 
    } 

    private string ModifyTextToFit(string text) 
    { 
     var result = text.Remove(MaxLength); 
     while (!string.IsNullOrEmpty(result) && !ValidateText(result)) 
      result = result.Remove(result.Length - 1); 

     return result; 
    } 

    private bool ValidateText(string text) 
    { 
     return LengthEncoding.GetByteCount(text) <= MaxLength; 
    } 
} 

XAML में मैं इस तरह इसका इस्तेमाल कर सकते हैं:

<DataTemplate DataType="{x:Type vm:StringViewModel}"> 
    <TextBox Text="{Binding Path=Value, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True}"> 
     <i:Interaction.Behaviors> 
      <b:TextBoxMaxLengthBehavior MaxLength="{Binding MaxLength}" LengthEncoding="{Binding LengthEncoding}" /> 
     </i:Interaction.Behaviors> 
    </TextBox> 
</DataTemplate> 

जहां xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"। मुझे आशा है कि इससे किसी और की मदद मिलेगी।

+1

प्रमाणीकरण नियम दृष्टिकोण का उपयोग क्यों नहीं करें ...? यह छोटा, पढ़ने में आसान है, और काम करता है ... और यह एक व्यवहार के रूप में पुन: प्रयोज्य है। –

+0

क्योंकि प्रमाणीकरण नियम के साथ उपयोगकर्ता अनुमति से अधिक टेक्स्टबॉक्स में अधिक वर्ण इनपुट कर सकता है। वह देखता है कि यह मान्य नहीं है लेकिन यह मेरा अपेक्षित व्यवहार नहीं था। मैं वास्तव में चाहता था कि उपयोगकर्ता इनपुट न करें। – scher

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