WPF 如何使用验证和绑定创建自定义文本框 [英] WPF How to create a Custom Textbox with validation and binding

查看:37
本文介绍了WPF 如何使用验证和绑定创建自定义文本框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发用于货币编辑的自定义文本框.
我见过一些现成的,但它们很复杂和/或不是真正可用,迫使您采取不良做法(例如硬编码应该在控件上使用的名称).
所以我决定自己做,但是我在使用绑定选项时遇到了麻烦,因为分配给绑定属性的属性必须是小数,但 TextBox 控件的 Text 属性接受字符串.
我想的答案是,也许,将访问方法(getter 和 setter)覆盖到基类 (TextBox) 中的 Text 属性,但这是不允许的.
我的绑定应该设置为值,该值将 TextBox 的文本属性设置为移动中的文本(带有货币符号和所有内容),但在 Get 方法中将其转换回数字数据类型.
这是我迄今为止取得的成就:

I'm developing a custom text box for currency editing.
I've seen some ready to use ones, but they're complicated and/or not really usable, forcing you to bad practices (such as hard coding the name that's supposed to be used on the control).
So I've decided to do it myself, but I'm having trouble to work with the binding options, since the property assigned to the binding attribute must be a decimal, but the Text property of the TextBox control accepts strings.
The answer I thought was, maybe, override the access methods (getters and setters) to the Text property in the base class (TextBox), but it is not allowed.
My binding should be set to the value, that sets the text property of the TextBox formatting it as text (with the currency symbols and everything) on the go, but converting it back to a numeric datatype on the Get method.
This is what I've achieved so far:

public class CurrencyTextBox : TextBox
    {
        private bool IsValidKey(Key key)
        {
            int k = (int)key;
            return ((k >= 34 && k <= 43) //digits 0 to 9
                || (k >= 74 && k <= 83) //numeric keypad 0 to 9
                || (k == 2) //back space
                || (k == 32) //delete
                );
        }
        private void Format()
        {
            //formatting decimal to currency text here
            //Done! no problems here
        }
        private void FormatBack()
        {
            //formatting currency text to decimal here
            //Done! no problems here
        }
        private void ValueChanged(object sender, TextChangedEventArgs e)
        {
            this.Format();
        }
        private void MouseClicked(object sender, MouseButtonEventArgs e)
        {
            this.Format();
            // Prevent changing the caret index
            this.CaretIndex = this.Text.Length;
            e.Handled = true;
        }
        private void MouseReleased(object sender, MouseButtonEventArgs e)
        {
            this.Format();
            // Prevent changing the caret index
            this.CaretIndex = this.Text.Length;
            e.Handled = true;
        }
        private void KeyPressed(object sender, KeyEventArgs e)
        {
            if (IsValidKey(e.Key))
                e.Handled = true;
            if (Keyboard.Modifiers != ModifierKeys.None)
                return;
            this.Format();
        }
        private void PastingEventHandler(object sender, DataObjectEventArgs e)
        {
            // Prevent copy/paste
            e.CancelCommand();
        }
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            // Disable copy/paste
            DataObject.AddCopyingHandler(this, PastingEventHandler);
            DataObject.AddPastingHandler(this, PastingEventHandler);
            this.CaretIndex = this.Text.Length;
            this.PreviewKeyUp += KeyPressed;
            this.PreviewMouseDown += MouseClicked;
            this.PreviewMouseUp += MouseReleased;
            this.TextChanged += ValueChanged;
            this.Format();
        }
    }

这是 XAML:

<MyNamespace:CurrencyTextBox x:Name="TxbCurrency" Text="{Binding Path=DataContext.Element.Currency, ValidatesOnDataErrors=True}" />

到目前为止一切顺利!从 decimal 属性到 TextBox 文本的绑定是正确的".但是现在的问题是如何在编辑后从文本中取回小数.
从十进制到 .Text 的绑定使用装箱来隐藏 ToString() 方法.
这里的问题:在这种情况下,如何从十进制重载 Parse() 方法以使用我的 FormatBack() 方法从 TextBox 的文本中获取小数?

So far so good! The binding from the decimal property to the TextBox text's is "right on". But how to get the decimal back from the text after it's editing is now the problem.
The binding from decimal to the .Text uses boxing to hide the ToString() method.
Question here: How can I overload the Parse() method from decimal in this case to use my FormatBack() method to get the decimal from the TextBox's Text?

推荐答案

像这样创建新的Dependency Property

public static readonly DependencyProperty ValueProperty = 
     DependencyProperty.Register(
         "Value", 
         typeof(decimal?),
         typeof(CurrencyTextBox),
         new FrameworkPropertyMetadata(
                     new decimal?(), 
                     FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, 
                     new PropertyChangedCallback(ValuePropertyChanged)));

private static void ValuePropertyChanged(
                         DependencyObject d,
                         DependencyPropertyChangedEventArgs e)
{
    CurrencyTextBox x = (CurrencyTextBox)d;
    x.Value = (decimal?)e.NewValue;
}

然后绑定到这个新属性

这篇关于WPF 如何使用验证和绑定创建自定义文本框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆