2010-06-16 14 views
6

Ben sil veya geri tuşuna aracılığıyla kullanıcı tarafından silinir hangi karakter izlemek istemektedir.WPF'de TextBox'ta hangi karakter silinir?

Ben metin kutusu TextBox_ChangedEvent taşıma ediyorum.

Ben TextChangedEventArgse.Changes ve evet ben nasıl yapabilirim eğer silinen karakteri ayıklamak miyim?

Ben TextBox herhangi karakterleri silmesini için kullanıcı sınırlamak istiyor. Ben kullanıcı

önermek Lütfen (")" "(" diyelim ya) sadece iki karakter silebilirsiniz istiyorum.

cevap

9

set Bırak

public static class TextInputBehaviour 
{ 
    public static bool GetIsDeleteRestricted(DependencyObject obj) 
    { 
     return (bool)obj.GetValue(IsDeleteRestrictedProperty); 
    } 

    public static void SetIsDeleteRestricted(DependencyObject obj, bool value) 
    { 
     obj.SetValue(IsDeleteRestrictedProperty, value); 
    } 

    public static readonly DependencyProperty IsDeleteRestrictedProperty=DependencyProperty.RegisterAttached("IsDeleteRestricted", typeof(bool), typeof(TextInputBehaviour), new UIPropertyMetadata(false, OnIsDeleteRestrictedChanged)); 
} 

private static void OnIsDeleteRestrictedChanged(object sender, DependencyPropertyChangedEventArgs e) 
{  
    TextBox textBox = (TextBox)sender; 
    bool isDeleteRestricted = (bool)(e.NewValue); 

    if (isDeleteRestricted) 
    textBox.PreviewKeyDown += RestrictDeleteKey; 
    else 
    textBox.PreviewKeyDown -= RestrictDeleteKey; 
} 

private static void RestrictDeleteKey(object sender, KeyEventArgs e) 
{ 
     e.Handled = (e.Key == Key.Delete); 
} 

TextBox'tan silinmek üzere "(" veya ")" bir şeyden kaçınmak için bu şekilde kullanılabilecek ekli bir özellik için.

birden fazla karakter ile Sil anahtarın
  1. Kullanım Geri tuşuna Ctrl- ait
  2. kullanı
  3. kullanın seçilmiş: Bu doğru gibi tüm fare ve klavye güncellemeleri, idare edecek

    <TextBox my:TextBoxRestriction.RestrictDeleteTo="()" ... /> 
    

    X kesmek için

  4. Menü çubuğunuzdaki "Kes" düğmesini tıklatarak

Bundan dolayı, PreviewKeyDown'ı basitçe yakalamaktan çok daha güçlüdür.

Bu aynı zamanda byt şey silinmesini devre dışı bırakır "(" veya ")" .Text doğrudan özelliğine atayarak, bu nedenle bu başarısız olur:

Bu nedenle
textBox.Text = "Good morning"; 

TextBoxRestriction sınıfı da başka ekli özelliği içeren UnrestrictedText olarak adlandırılan, ayarlandığında, kısıtlamaları atlayarak Metin özelliğini güncelleyebilir.Bu TextBoxRestriction.SetUnrestrictedText kullanarak kod ayarlanabilir veya böyle veriyle: RestrictDeleteTo da ayarlandığında aşağıdaki uygulamada

<TextBox my:TextBoxRestriction.RestrictDeleteTo="()" 
     my:TextBoxRestriction.UnrestrictedText="{Binding PropertyNameHere}" /> 

, UnrestrictedText çalışır. Bir özellik her ayarlandığında olay işleyiciyi kaydettiren ve daha sonra kayıt dışı tutmak için işleyiciyi üçüncü bir ekli eşyaya kaydeden tam bir uygulama yapılabilir. Ancak mevcut ihtiyaçlarınız için muhtemelen gereksizdir. İşte

söz verildiği gibi uygulamasıdır:

Nasıl Çalışır
public class TextBoxRestriction : DependencyObject 
{ 
    // RestrictDeleteTo: Set this to the characters that may be deleted 
    public static string GetRestrictDeleteTo(DependencyObject obj) { return (string)obj.GetValue(RestrictDeleteToProperty); } 
    public static void SetRestrictDeleteTo(DependencyObject obj, string value) { obj.SetValue(RestrictDeleteToProperty, value); } 
    public static readonly DependencyProperty RestrictDeleteToProperty = DependencyProperty.RegisterAttached("RestrictDeleteTo", typeof(string), typeof(TextBoxRestriction), new PropertyMetadata 
    { 
    PropertyChangedCallback = (obj, e) => 
     { 
     var box = (TextBox)obj; 
     box.TextChanged += (obj2, changeEvent) => 
      { 
      var oldText = GetUnrestrictedText(box); 
      var allowedChars = GetRestrictDeleteTo(box); 
      if(box.Text==oldText || allowdChars==null) return; 

      foreach(var change in changeEvent.Changes) 
       if(change.RemovedLength>0) 
       { 
       string deleted = box.Text.Substring(change.Offset, change.RemovedLength); 
       if(deleted.Any(ch => !allowedChars.Contains(ch))) 
        box.Text = oldText; 
       } 
      SetUnrestrictedText(box, box.Text); 
      }; 
     } 
    }); 

    // UnrestrictedText: Bind or access this property to update the Text property bypassing all restrictions 
    public static string GetUnrestrictedText(DependencyObject obj) { return (string)obj.GetValue(UnrestrictedTextProperty); } 
    public static void SetUnrestrictedText(DependencyObject obj, string value) { obj.SetValue(UnrestrictedTextProperty, value); } 
    public static readonly DependencyProperty UnrestrictedTextProperty = DependencyProperty.RegisterAttached("UnrestrictedText", typeof(string), typeof(TextBoxRestriction), new PropertyMetadata 
    { 
    DefaultValue = "", 
    PropertyChangedCallback = (obj, e) => 
     { 
     var box = (TextBox)obj; 
     box.Text = (string)e.NewValue; 
     } 
    }); 

} 

: Eğer UnrestrictedText ayarladığınızda o tersi Metin ve ayarlar. TextChanged işleyicisi, Metnin UnrestrictedText öğesinden farklı olup olmadığını kontrol eder. Eğer öyleyse, Metin'in UnrestrictedText'i ayarlamaktan başka bir mekanizma tarafından güncellendiğini biliyor, böylece yasadışı bir silme için yapılan değişiklikleri tarar. Biri bulunursa, metni UnrestrictedText'de saklanan değere geri döndürerek değişikliği engeller.

+0

Büyük yardım! Bir kullanıcının silme girişiminde bulunduğu son karakterin silinmesini önlemek için biraz değiştirdim. – alan

0

Ben WPF biliyorum ama bunun için WinForms aynı şey olduğunu varsayarak (muhtemel görünüyor) yoktur. Bildiğim tek yol, geçerli metni bir değişkende ve metin değiştirmede tutmanızdır. Eğer bu bir silme veya geri alan değilse, bu metni güncellersiniz, aksi takdirde onu neyin değiştiğini karşılaştırın ve bu değişikliğe izin verilmelidir.

Düzenleme: TextChangedEventArgs.Changes'a baktığımda, yukarıda anlattığım yolun hala devam etmenin yolu olabileceği izlenimi veriyor, ancak metinleri daha verimli bir şekilde karşılaştırmak için Changes'u kullanabiliyor olabilirsiniz.

Bunu zaten düşünmüş olabilirsiniz, ancak aksi halde, kesmeyi ve yapıştırmayı da unutmayın (ve kullanıcının bunu klavyeden ziyade fare ile yapıyor olabileceğini unutmayın).

1

Ekli davranış işlemek için o kodu aşağıda bulabilirsiniz kaynakları bölümüne sizin metin kutusu biçimlendirme bloğunda Sonra

yılında davranışları, davranış

<TextBox local:TextInputBehaviour.IsDeleteRestricted="True" /> 
+0

@Ashish: '(' ve ')' gibi karakterleri silme konusunda bazı istisnalarınız varsa, bu koşulları RestrictDeletedKey yöntemine ekleyin. – Amsakanna