Q:

Bypassing TextChanged event at specific time

I have set up custom textboxes that strip out everything except numbers, then add formatting to reflect phone# format (###-###-####).  The Replace method is contained within the TextChanged event in order to cover typing or pasting by mouse or keyboard.  The formatting is done through the LostFocus event, as it wouldn't be able to format correctly until all numbers are there.  My problem is, the TextChanged event fires after the LostFocus event, so all the formatting is erased as soon as it's added.  Is there a way to bypass TextChanged at this specific time?  Or a better way to organize the events?
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

}

}

A:

You could implement a flag thusly:
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);
    }
}

Local boolean variable defaulted to false is set true only when OnLostFocus is entered.  When entering OnTextChanged property is checked and if true, the logic is bypassed and property is reset.

