2010-06-16 25 views
6

我想跟蹤用戶通過Delete或BackSpace Key刪除哪個字符。如何跟蹤哪些字符在WPF中的TextBox中被刪除?

我正在處理文本框的TextBox_ChangedEvent。

我可以提取TextChangedEventArgse.Changes,如果是我該怎麼做刪除字符?

我想限制用戶從文本框中刪除任何字符。我想用戶只能刪除兩個字符(比如說「(」或「)」)

請建議。

回答

9

下面你會發現代碼對於可以像這樣使用的附加屬性來防止從「TextBox」句柄中刪除「(」或「)」以外的任何內容。

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

這將正確處理所有的鼠標和鍵盤的更新,如:

  1. 使用帶有多個字符刪除鍵的選擇
  2. 使用退格鍵
  3. 中使用Ctrl-的X剪切
  4. 點擊菜單欄上的「剪切」按鈕

正因爲如此,它比攔截PreviewKeyDown功能強大得多。

這也將禁止任何BYT刪除「(」或「)」通過直接的。文本屬性分配,所以這將失敗:

textBox.Text = "Good morning"; 

正因爲如此的TextBoxRestriction類還包含另一個附加屬性稱爲無限制文本其中,設置時,能夠繞過限制更新文本屬性。這可以在代碼中使用TextBoxRestriction.SetUnrestrictedText進行設置,或者數據綁定這樣的:

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

在下面的實施,UnrestrictedText當RestrictDeleteTo也設置纔有效。完整的實現可以在任何屬性設置時註冊事件處理程序,並將處理程序保存在第三個附屬屬性中,以便以後取消註冊。但是對於您當前的需求可能是不必要的。

下面是實現的承諾:

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

} 

工作原理:當您設置UnrestrictedText它集文字,反之亦然。 TextChanged處理程序檢查是否Text與UnrestrictedText不同。如果是這樣,它知道文本已通過除設置UnrestrictedText之外的其他機制進行更新,因此將掃描非法刪除的更改。如果發現其中一個,則將Text設置回仍保存在UnrestrictedText中的值,以防止更改。

+0

巨大的幫助!我稍微修改它以防止刪除用戶嘗試刪除的最後一個字符。 – alan 2011-04-07 02:41:14

0

我不知道WPF,但假設它與此WinForms相同(似乎很可能)。我知道的唯一方法是,您實際上將當前文本保留在變量和文本更改中,如果它不是刪除或退格,則更新該文本,否則使用它比較已更改的內容以及是否允許更改。

編輯:看TextChangedEventArgs.Changes看起來我上面描述的方式可能仍然是要走的路,但您也許可以使用Changes來更有效地比較文本。

您可能已經考慮過了,但除此之外,請記住也要處理剪切和粘貼(並且用戶可能會用鼠標而不是鍵盤來完成)。

1

附加的行爲來處理它

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 local:TextInputBehaviour.IsDeleteRestricted="True" /> 
+0

@Ashish:如果您在刪除'('和')'等字符時出現了一些異常,請在RestrictDeletedKey方法中添加這些條件。 – Amsakanna 2010-06-16 08:58:27

相關問題