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

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

问题描述

我正在开发用于货币编辑的自定义文本框.
我已经看到了一些可以立即使用的工具,但是它们很复杂和/或无法真正使用,迫使您采取不良做法(例如,硬编码应该在控件上使用的名称).
所以我决定自己做,但是我在使用绑定选项时遇到了麻烦,因为分配给binding属性的属性必须是十进制,但是TextBox控件的Text属性可以接受字符串. > 我认为的答案可能是,重写基类(TextBox)中Text属性的访问方法(getter和setter),但不允许这样做.
我的绑定应该设置为值,该值设置TextBox的text属性,可以随时随地将其设置为文本格式(包含货币符号和所有内容),但可以在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}" />

到目前为止一切顺利!从十进制属性到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天全站免登陆