如何在不影响用户输入的情况下设置文本框的数字格式?

时间:2016-04-27 09:08:33

标签: c# wpf

我在动态WPF应用程序上使用VS 2015,其中控件及其绑定在代码隐藏中生成。 现在我想实现一个TextBox,它绑定到double类型的数据表列。 此外,在我的TextBox的构建器类中,我尝试设置Format和MaxLength。 一切正常。 格式和MaxLength都可以,但是当我想输入或编辑某些内容时,这很难做到。 客户永远不会接受。 我该怎么办?

这里我称之为构建器类:

CreateTextbox(viewmodel, "table1", "Menge", 20, 40, 60, "#0.0000", 2, 4);

这是创建并返回TextBox的公共方法。

/// <summary>
/// Create and returns a textbox.
/// </summary>
/// <param name="viewmodel">The viewmodel.</param>
/// <param name="tablename">The name of the datatable.</param>
/// <param name="sourceColumn">The column to which we want to bind the textbox.</param>
/// <param name="leftPos">The left position.</param>
/// <param name="topPos">The top position.</param>
/// <param name="width">The width of the textbox.</param>
/// <param name="format">The format of the value.</param>
/// <param name="integerPositions">The integerpositions before the comma.</param>
/// <param name="decimalPlaces">The decimal places after the comma.</param>
/// <returns>Returns an object of type TextBox.</returns>
public TextBox CreateTextbox(MainViewModel viewmodel, string tablename, string sourceColumn, double leftPos, double topPos,
    double width, string format="", int integerPositions=0, int decimalPlaces=0)
{
    // Textbox is created.
    TextBox textbox = new TextBox();
    textbox.Width = width;
    Canvas.SetLeft(textbox, leftPos);
    Canvas.SetTop(textbox, topPos);

    // Now the binding to the datasource is initialized.
    Binding controlbinding = new Binding();
    controlbinding.Source = viewmodel.ApplicationDataSet.Tables[tablename].DefaultView;
    controlbinding.Path = new PropertyPath("[0][" + sourceColumn + "]");
    if (!string.IsNullOrWhiteSpace(format))
    {
        controlbinding.StringFormat = format;
        textbox.MaxLength = integerPositions + decimalPlaces + 1;
        ////controlbinding.ValidationRules = ???;
    }
    controlbinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
    textbox.SetBinding(TextBox.TextProperty, controlbinding);

    return textbox;
}

YYYY

1 个答案:

答案 0 :(得分:0)

您可以尝试创建例如一种看似类似的行为:

public class TextBoxNumericalOnlyBehavior : Behavior<Control>
    {
        private TextBox textBox;

        public static readonly DependencyProperty MaxValueProperty =
        DependencyProperty.Register("MaxValue", typeof(Double), typeof(TextBoxNumericalOnlyBehavior),
        new FrameworkPropertyMetadata(Double.MaxValue));

        public Double MaxValue
        {
            get
            {
                return (Double)base.GetValue(MaxValueProperty);
            }
            set
            {
                base.SetValue(MaxValueProperty, value);
            }
        }

        public static readonly DependencyProperty MinValueProperty =
        DependencyProperty.Register("MinValue", typeof(Double), typeof(TextBoxNumericalOnlyBehavior),
        new FrameworkPropertyMetadata(Double.MinValue));

        public Double MinValue
        {
            get
            {
                return (Double)base.GetValue(MinValueProperty);
            }
            set
            {
                base.SetValue(MinValueProperty, value);
            }
        }

        public static readonly DependencyProperty RegularExpressionProperty =
        DependencyProperty.Register("RegularExpression", typeof(string), typeof(TextBoxNumericalOnlyBehavior),
        new FrameworkPropertyMetadata(".*"));
        public string RegularExpression
        {
            get
            {
                return (string)base.GetValue(RegularExpressionProperty);
            }
            set
            {
                base.SetValue(RegularExpressionProperty, value);
            }
        }

        protected override void OnAttached()
        {
            base.OnAttached();

            AssociatedObject.Loaded += AssociatedObject_Loaded;
            AssociatedObject.Unloaded += AssociatedObject_Unloaded;
            AssociatedObject.PreviewKeyDown += AssociatedObject_PreviewKeyDown;
            AssociatedObject.PreviewTextInput += AssociatedObject_PreviewTextInput;
            DataObject.AddPastingHandler(AssociatedObject, OnPaste);
        }

        private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
        {
            // to do
        }

        private void AssociatedObject_Unloaded(object sender, RoutedEventArgs e)
        {
            // to do
        }

        private void AssociatedObject_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (this.textBox != null)
            {
                if (e.Key == Key.Space || e.Key == Key.Delete)
                {
                    e.Handled = true;
                }
                else if (e.Key == Key.Back)
                {
                    e.Handled = !IsValid(string.Empty, false, true);
                }
            }
        }

        private void AssociatedObject_PreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            if (this.textBox != null)
            {
                e.Handled = !IsValid(e.Text, false, false);
            }
        }

        private void OnPaste(object sender, DataObjectPastingEventArgs e)
        {
            if (e.DataObject.GetDataPresent(DataFormats.Text))
            {
                string text = Convert.ToString(e.DataObject.GetData(DataFormats.Text));

                if (!IsValid(text, true, false))
                {
                    e.CancelCommand();
                }
            }
            else
            {
                e.CancelCommand();
            }
        }

        private bool IsValid(string text, bool paste, bool back)
        {
            if(this.textBox.Text == null)
            {
                return false;
            }

            int caretIndex = this.textBox.CaretIndex;
            int selectionStart = this.textBox.SelectionStart;
            int selectionLength = this.textBox.SelectionLength;

            string newValue = string.Empty;

            // on paste 
            if (paste && selectionLength > 0)
            {
                string tempValue = this.textBox.Text.Remove(selectionStart, selectionLength);
                newValue = tempValue.Insert(caretIndex, text.Trim());
            }
            // on back
            else if (back)
            {
                // check if textbox is empty
                if (this.textBox.Text.Equals(string.Empty))
                {
                    return true;
                }

                newValue = this.textBox.Text.Remove(selectionStart == 0 ? selectionStart : selectionStart - 1,
                    selectionLength == 0 ? 1 : selectionLength);
            }
            else
            {
                newValue = this.textBox.Text.Insert(caretIndex, text.Trim());
            }

            return IsInRange(newValue);
        }

        private bool IsInRange(string text)
        {
            Double result = 0;

            if (text.Equals(string.Empty))
            {
                return true;
            }

            if (Regex.IsMatch(text, this.RegularExpression))
            {
                if (Double.TryParse(text, out result))
                {
                    return result <= this.MaxValue && result >= this.MinValue;
                }
            }

            return false;
        }
}

和.xaml:

<i:Interaction.Behaviors>
     <commonBehaviors:TextBoxNumericalOnlyBehavior MaxValue="99.99"
                                                   MinValue="0.00"
                                               RegularExpression="^(\d{0,2})(\.\d{0,2})?$"/>
 </i:Interaction.Behaviors>

常规exp:RegularExpression="^(\d{0,2})(\.\d{0,2})?$"/>将仅允许00.00格式,但假设RegularExpression="^(\d{0,4})(\.\d{0,2})?$"/>将允许0000.00。 Max和Min Values设置输入范围。