2010-06-16 5 views
6

삭제 또는 백스 페이스 키를 통해 사용자가 삭제 한 문자를 추적하고자합니다.WPF의 TextBox에서 삭제되는 문자를 추적하는 방법은 무엇입니까?

텍스트 상자의 TextBox_ChangedEvent를 처리하고 있습니다.

나는 TextChangedEventArgse.Changes 그래 내가 어떻게 할 수 있다면에서 삭제 된 문자를 추출 할 수 있습니까?

사용자가 텍스트 상자에서 문자를 삭제하지 못하도록 제한하고 싶습니다. 사용자가 두 글자 만 지울 수 있기를 원합니다 ("("또는 ")"라고 말하십시오)

제안 해주십시오.

답변

9

을 설정 드롭

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에서 삭제되는 것을 막기 위해 이와 같이 사용할 수있는 첨부 된 속성의 경우 마침표.

여러 문자 Delete 키의
  1. 사용이 백 스페이스 키 CTRL-의
  2. 이용
  3. 사용을 선택이 올바르게 같은 모든 마우스와 키보드 업데이트를 처리 할

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

    X 잘라 내기

  4. 메뉴 모음에서 "잘라 내기"버튼을 클릭하십시오.

이 때문에 단순히 PreviewKeyDown을 가로채는 것보다 훨씬 강력합니다.

이것은 또한 BYT 아무것도 삭제하지 않습니다 "("또는 ")"는는 .text 속성에 직접 할당하여, 그래서 이것은 실패합니다

이 때문에
textBox.Text = "Good morning"; 

는 TextBoxRestriction 클래스가 또 다른 연결된 속성을 포함 UnrestrictedText을 호출하면 제한을 무시하고 Text 속성을 업데이트 할 수 있습니다.이것은 TextBoxRestriction.SetUnrestrictedText를 사용하여 코드에서 설정 될 수 있으며,이 같은 데이터 바인딩 : RestrictDeleteTo도 설정되어있는 경우 아래의 구현에서

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

이 UnrestrictedText 만 작동합니다. 두 속성 중 하나가 설정 될 때마다 이벤트 처리기를 등록하고 나중에 등록 해제를 위해 세 번째 연결된 속성에 처리기를 저장하는 전체 구현을 만들 수 있습니다. 그러나 현재 필요로하는 것은 아마도 불필요합니다. 여기

약속으로 구현 한 것입니다 :

작동 원리
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에 저장된 값으로 Text를 다시 설정하여 변경을 방지합니다.

+0

큰 도움! 사용자가 삭제하려고하는 마지막 문자의 삭제를 방지하기 위해 약간 수정했습니다. – alan

0

WPF는 모르겠지만 WinForms와 동일하다고 가정합니다 (가능성이 있음). 내가 아는 유일한 방법은 현재 텍스트를 변수에 유지하고 텍스트를 변경할 때 삭제 또는 백 스페이스가 아닌 경우 해당 텍스트를 업데이트하는 것입니다. 그렇지 않으면 변경된 내용과 비교하여 변경 사항을 허용해야합니다.

편집 : 내가 위에서 설명한 방법과 같아 보이지만 더 효율적으로 텍스트를 비교하기 위해 Changes을 사용할 수 있습니다. TextChangedEventArgs.Changes

이미 생각해봤을 지 모르겠지만 잘라 내기 및 붙여 넣기도 처리해야합니다. 키보드를 사용하는 대신 사용자가 마우스로 작업 할 수도 있습니다.

1

연결된 동작을 처리하는 것이 당신이 코드를 찾을 수 아래 리소스 섹션하여 텍스트 상자 마크 업 블록에서 다음

의 행동, 행동

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

@Ashish : '('및 ')'과 같은 문자를 삭제하는 경우 예외가있는 경우 RestrictDeletedKey 메소드에 해당 조건을 추가하십시오. – Amsakanna

관련 문제