2011-12-08 57 views
1

我设置了除数字以外的所有内容的自定义文本框,然后添加格式以反映手机#格式(### - ### - ####)。 Replace方法包含在TextChanged事件中,以覆盖鼠标或键盘的输入或粘贴。格式化是通过LostFocus事件完成的,因为直到所有数字都存在才能正确格式化。我的问题是,TextChanged事件在LostFocus事件之后触发,所以所有的格式都会在添加后立即被删除。有没有在这个特定时间绕过TextChanged的方法?或者更好的方式来组织这些事件?在特定时间绕过TextChanged事件

namespace CustomTextBoxes 
{ 
public class NumberTextBox : Control 
{ 

} 

public class WatermarkTextBox : TextBox 
{ 
    public byte bypassEvent = 0; 

    #region Properties 

    #region SelectAllOnGotFocus 

    public static readonly DependencyProperty SelectAllOnGotFocusProperty = DependencyProperty.Register("SelectAllOnGotFocus", typeof(bool), typeof(WatermarkTextBox), new PropertyMetadata(false)); 
    public bool SelectAllOnGotFocus 
    { 
     get { return (bool)GetValue(SelectAllOnGotFocusProperty); } 
     set { SetValue(SelectAllOnGotFocusProperty, value); } 
    } 

    #endregion //SelectAllOnGotFocus 

    #region Watermark 

    public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register("Watermark", typeof(object), typeof(WatermarkTextBox), new UIPropertyMetadata(null)); 
    public object Watermark 
    { 
     get { return (object)GetValue(WatermarkProperty); } 
     set { SetValue(WatermarkProperty, value); } 
    } 

    #endregion //Watermark 

    #region WatermarkTemplate 

    public static readonly DependencyProperty WatermarkTemplateProperty = DependencyProperty.Register("WatermarkTemplate", typeof(DataTemplate), typeof(WatermarkTextBox), new UIPropertyMetadata(null)); 
    public DataTemplate WatermarkTemplate 
    { 
     get { return (DataTemplate)GetValue(WatermarkTemplateProperty); } 
     set { SetValue(WatermarkTemplateProperty, value); } 
    } 

    #endregion //WatermarkTemplate 

    #endregion //Properties 

    #region Constructors 

    static WatermarkTextBox() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(WatermarkTextBox), new FrameworkPropertyMetadata(typeof(WatermarkTextBox))); 
    } 

    #endregion //Constructors 

    #region Base Class Overrides 

    protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e) 
    { 
     base.OnGotKeyboardFocus(e); 

     if (SelectAllOnGotFocus) 
      SelectAll(); 
     else 
      SelectionLength = 0; 
    } 

    protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) 
    { 
     if (!IsKeyboardFocused && SelectAllOnGotFocus) 
     { 
      e.Handled = true; 
      Focus(); 
     } 

     base.OnPreviewMouseLeftButtonDown(e); 
    } 

    #endregion //Base Class Overrides 
} 

public class DigitBox : WatermarkTextBox 
{ 
    #region Constructors 
    ///<summary> 
    ///The default constructor 
    /// </summary> 
    public DigitBox() 
    { 
     TextChanged += new TextChangedEventHandler(OnTextChanged); 
     KeyDown += new KeyEventHandler(OnKeyDown); 
     PreviewKeyDown += new KeyEventHandler(OnPreviewDown); 
     LostFocus += new RoutedEventHandler(OnLostFocus); 
    } 
    #endregion 

    #region Properties 
    new public String Text 
    { 
     get { return base.Text; } 
     set 
     { 
      base.Text = LeaveOnlyNumbers(value); 
     } 
    } 
    #endregion 

    #region Functions 
    public bool IsNumberKey(Key inKey) 
    { 
     if (inKey < Key.D0 || inKey > Key.D9) 
     { 
      if (inKey < Key.NumPad0 || inKey > Key.NumPad9) 
      { 
       return false; 
      } 
     } 
     return true; 
    } 

    public bool IsActionKey(Key inKey) 
    { 
     return inKey == Key.Delete || inKey == Key.Back || inKey == Key.Tab || inKey == Key.Return; 
    } 

    public virtual string LeaveOnlyNumbers(String inString) 
    { 
     String tmp = inString; 
     foreach (char c in inString.ToCharArray()) 
     { 

      if (!IsDigit(c)) 
      { 
       tmp = tmp.Replace(c.ToString(), ""); 
      } 

     } 
     return tmp; 
    } 

    public bool IsDigit(char c) 
    { 
     double num; 
     return (double.TryParse(c.ToString(), out num)); 
    } 

    public bool IsSpaceKey(Key inKey) 
    { 
     if (inKey == Key.Space) 
     { 
      return true; 
     } 
     return false; 
    } 
    #endregion 

    #region Event Functions 
    protected virtual void OnKeyDown(object sender, KeyEventArgs e) 
    { 
     e.Handled = !IsNumberKey(e.Key) && !IsActionKey(e.Key) && !IsSpaceKey(e.Key); 
    } 

    protected virtual void OnTextChanged(object sender, TextChangedEventArgs e) 
    { 
     base.Text = LeaveOnlyNumbers(Text);    
    } 

    protected virtual void OnPreviewDown(object sender, KeyEventArgs e) 
    { 
     if (e.Key == Key.Space) 
     { 
      e.Handled = true; 
     } 
    } 

    protected virtual void OnLostFocus(object sender, RoutedEventArgs e) 
    { 
     base.Text = base.Text; 
    } 
    #endregion 
} 

public class DateBox : DigitBox 
{ 
    #region Functions 
    private bool IsFormattingKey(Key inKey) 
    { 
     return inKey == Key.OemPeriod || inKey == Key.OemMinus || inKey == Key.Oem2; 
    } 

    public override string LeaveOnlyNumbers(String inString) 
    { 
     String tmp = inString; 
     foreach (char c in inString.ToCharArray()) 
     { 

      if (!IsDigit(c)) 
      { 
       //if (c != '/') 
       //{ 
       // tmp = tmp.Replace(c.ToString(), ""); 
       //} 
      } 

     } 
     return tmp; 
    } 
    #endregion 

    #region Event Functions 
    protected override void OnKeyDown(object sender, KeyEventArgs e) 
    { 
     e.Handled = !IsNumberKey(e.Key) && !IsActionKey(e.Key) && !IsFormattingKey(e.Key) && !IsSpaceKey(e.Key); 
    } 

    protected override void OnLostFocus(object sender, RoutedEventArgs e) 
    { 
     string content = Text; 
     char[] contents = content.ToCharArray(); 

     if (content.Length == 8) 
     { 
      base.Text = Text.Substring(0, 2) + "/" + Text.Substring(2, 2) + "/" + Text.Substring(4, 4); 
     } 
     else if (content.Length == 6) 
     { 
      int century = Convert.ToInt32(DateTime.Today.Year.ToString().Substring(2, 2)); 
      string tempCentury = content[4].ToString() + content[5].ToString(); 
      int unknownCentury = Convert.ToInt32(tempCentury); 
      if (unknownCentury > century + 1) 
      { 
       base.Text = Text.Substring(0, 2) + "/" + Text.Substring(2, 2) + "/" + "19" + Text.Substring(4, 2); 
      } 
      else base.Text = Text.Substring(0, 2) + "/" + Text.Substring(2, 2) + "/" + "20" + Text.Substring(4, 2); 
     } 
     else if (content.Length == 4) 
     { 
      base.Text = Text.Substring(0, 1) + "/" + Text.Substring(1, 1) + "/" + Text.Substring(2, 2); 
      int century = Convert.ToInt32(DateTime.Today.Year.ToString().Substring(2, 2)); 
      string tempCentury = content[4].ToString() + content[5].ToString(); 
      int unknownCentury = Convert.ToInt32(tempCentury); 
      if (unknownCentury > century + 1) 
      { 
       base.Text = Text.Substring(0, 2) + "/" + Text.Substring(2, 2) + "/" + "19" + Text.Substring(4, 2); 
      } 
      else base.Text = Text.Substring(0, 2) + "/" + Text.Substring(2, 2) + "/" + "20" + Text.Substring(4, 2); 
     } 
    } 
    #endregion 
} 

public class PhoneBox : DigitBox 
{ 
    private bool IsFormattingKey(Key inKey) 
    { 
     return inKey == Key.OemPeriod || inKey == (Key.LeftShift | Key.D9) || inKey == (Key.RightShift | Key.D9) || inKey == (Key.LeftShift | Key.D0) || 
      inKey == (Key.RightShift | Key.D0); 
    } 

    public override string LeaveOnlyNumbers(String inString) 
    { 
     String tmp = inString; 
     foreach (char c in inString.ToCharArray()) 
     { 

      if (!IsDigit(c)) 
      { 

        tmp = tmp.Replace(c.ToString(), ""); 

      } 

     } 
     return tmp; 
    } 

    #region Event Functions 
    protected override void OnKeyDown(object sender, KeyEventArgs e) 
    { 
     e.Handled = !IsNumberKey(e.Key) && !IsActionKey(e.Key) && !IsFormattingKey(e.Key) && !IsSpaceKey(e.Key); 
    } 

    protected override void OnLostFocus(object sender, RoutedEventArgs e) 
    { 
     bypassEvent = 1; 
     string content = Text; 
     char[] contents = content.ToCharArray(); 

     if (content.Length == 10) 
     { 
      base.Text = Text.Substring(0, 3) + "-" + Text.Substring(3, 3) + "-" + Text.Substring(6, 4); 
     } 
    } 
    #endregion 

} 

}

+1

在您的LostFocus中设置一个标志? – sq33G

+0

对不起,但你是什么意思? –

+1

我认为他的意思是,设置一个布尔属性(让我们称之为LosingFocus)默认为False。在LostFocus甚至处理程序中,将其设置为True。在您的TextChanged事件处理程序中,选中LosingFocus。如果为True,则通过退出处理事件,如果为false,则执行正常的事件处理程序逻辑。通过这种方式,TextChanged事件处理程序可以根据之前发生的事情决定是否执行。 (确保在退出OnTextChanged之前将LosingFocus设置为false – CodeWarrior

回答

1

你可能正是如此实现的标志:

private bool LosingFocus = false; 


protected virtual void OnTextChanged(object sender, TextChangedEventArgs e) 
{ 
    if (LosingFocus != true) 
    { 
    base.Text = LeaveOnlyNumbers(Text); 
    } 
    LosingFocus = false; 
} 


protected override void OnLostFocus(object sender, RoutedEventArgs e) 
{ 
    LosingFocus = true; 
    string content = Text; 
    char[] contents = content.ToCharArray(); 

    if (content.Length == 8) 
    { 
     base.Text = Text.Substring(0, 2) + "/" + Text.Substring(2, 2) + "/" + Text.Substring(4, 4); 
    } 
    else if (content.Length == 6) 
    { 
     int century = Convert.ToInt32(DateTime.Today.Year.ToString().Substring(2, 2)); 
     string tempCentury = content[4].ToString() + content[5].ToString(); 
     int unknownCentury = Convert.ToInt32(tempCentury); 
     if (unknownCentury > century + 1) 
     { 
      base.Text = Text.Substring(0, 2) + "/" + Text.Substring(2, 2) + "/" + "19" + Text.Substring(4, 2); 
     } 
     else base.Text = Text.Substring(0, 2) + "/" + Text.Substring(2, 2) + "/" + "20" + Text.Substring(4, 2); 
    } 
    else if (content.Length == 4) 
    { 
     base.Text = Text.Substring(0, 1) + "/" + Text.Substring(1, 1) + "/" + Text.Substring(2, 2); 
     int century = Convert.ToInt32(DateTime.Today.Year.ToString().Substring(2, 2)); 
     string tempCentury = content[4].ToString() + content[5].ToString(); 
     int unknownCentury = Convert.ToInt32(tempCentury); 
     if (unknownCentury > century + 1) 
     { 
      base.Text = Text.Substring(0, 2) + "/" + Text.Substring(2, 2) + "/" + "19" + Text.Substring(4, 2); 
     } 
     else base.Text = Text.Substring(0, 2) + "/" + Text.Substring(2, 2) + "/" + "20" + Text.Substring(4, 2); 
    } 
} 

局部布尔变量默认为false设置为true进入OnLostFocus只有当。当进入OnTextChanged属性被选中并且如果为true,逻辑被绕过并且属性被重置。

+0

我会在我回家的时候尝试一下,但是我真的使用int来做类似的事情,并且它完全停止了格式化。也许我输错了:) –

+0

好的,所以它确实工作(主要是),我只需要改变检查标志的位置。我没有将它放在OnTextChanged方法中,而是将它移到了LeaveOnlyNumbers方法中。最终不是导致问题的TextChanged事件,而是事件_called_的方法。感谢您的帮助,但我不会再回来,并尝试再次没有您(&sq33G)的帮助。 –