在特定时间绕过TextChanged事件

时间:2011-12-08 15:49:06

标签: c# wpf events textbox formatting

我已设置自定义文本框,除去数字之外的所有内容,然后添加格式以反映phone#format(### - ### - ####)。 Replace方法包含在TextChanged事件中,以便通过鼠标或键盘进行键入或粘贴。格式化是通过LostFocus事件完成的,因为在所有数字都存在之前它无法正确格式化。我的问题是,TextChanged事件在LostFocus事件之后触发,因此所有格式化一旦添加就会被删除。有没有办法绕过这个特定时间的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 个答案:

答案 0 :(得分: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);
    }
}

只有在输入OnLostFocus时,默认设置为false的本地布尔变量才会设置为true。当选中输入OnTextChanged属性时,如果为true,则绕过逻辑并重置属性。