CodeGo.net>数字文本框-使用Double.TryParse

我知道这是一个古老的问题,有很多答案,但是我还没有找到任何好的,可靠的答案.

要求是一个文本框,该文本框将始终包含Double.TryParse将在其上返回true的字符串.

我见过的大多数实现都不反对输入,例如:“ 10.45.8”.这是个问题.

最好的方法是完全使用事件,例如TextInput和KeyDown(用于空格).这些问题是要获得一个字符串,它表示更改之前的新文本(或更改之后的旧文本)非常复杂. TextChanged的问题在于它没有提供获取旧Text的方法.

如果您能以某种方式在更改之前获取新Text,那将是最有帮助的,因为您可以针对Double.TryParse对其进行测试.不过,可能会有更好的解决方案.

做这个的最好方式是什么?

对此问题的最佳答案是采用几种方法进行比较.

解决方法:

方法1

对TextBox使用TextChanged和KeyDown事件的组合.在KeyDown上,您可以将当前文本保存在文本框中,然后在TextChanged事件中执行Double.TryParse.如果输入的文本无效,那么您将还原为旧文本值.看起来像:

private int oldIndex = 0;
private string oldText = String.Empty;

private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
{
    double val;
    if (!Double.TryParse(textBox1.Text, out val))
    {
        textBox1.TextChanged -= textBox1_TextChanged;
        textBox1.Text = oldText;
        textBox1.CaretIndex = oldIndex;
        textBox1.TextChanged += textBox1_TextChanged;
    }
}

private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
    oldIndex = textBox1.CaretIndex;
    oldText = textBox1.Text;
}

CaratIndex有助于在验证失败时将光标移到第一个位置,不会使用户烦恼.但是,此方法不能捕获空格键.它将允许像“ 1234.56”这样输入文本.此外,粘贴文本将无法正确验证.除此之外,我不喜欢在文本更新过程中弄乱事件处理程序.

方法2

这种方法应该可以满足您的需求.

使用PreviewKeyDown和PreviewTextInput事件处理程序.通过观看这些事件并进行相应的处理,您无需担心在文本框中恢复为先前的文本值. PreviewKeyDown可用于监视和忽略您的SpaceBar键,PreviewTextInput可用于在分配新的文本框值之前对其进行测试.

private void textBox1_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Space)
    {
        e.Handled = true;
    }
}

private void textBox1_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
    //Create a string combining the text to be entered with what is already there.
    //Being careful of new text positioning here, though it isn't truly necessary for validation of number format.
    int cursorPos = textBox1.CaretIndex;
    string nextText;
    if (cursorPos > 0)
    {
        nextText = textBox1.Text.Substring(0, cursorPos) + e.Text + textBox1.Text.Substring(cursorPos);
    }
    else
    {
        nextText = textBox1.Text + e.Text;
    }
    double testVal;
    if (!Double.TryParse(nextText, out testVal))
    {
        e.Handled = true;
    }
}

这种方法可以更好地捕获无效输入,然后再将其输入文本框.但是,我认为将事件设置为Handled可能会使您陷入麻烦,具体取决于消息路由列表中的其他目标.此处未处理的最后一项是用户将无效输入粘贴到文本框中的能力.可以通过添加此代码(从Paste Event in a WPF TextBox开始构建)来处理.

private void OnPaste(object sender, DataObjectPastingEventArgs e)
{
    double testVal;
    bool ok = false;

    var isText = e.SourceDataObject.GetDataPresent(System.Windows.DataFormats.Text, true);
    if (isText)
    {
        var text = e.SourceDataObject.GetData(DataFormats.Text) as string;
        if (Double.TryParse(text, out testVal))
        {
            ok = true;
        }
    }

    if (!ok)
    {
        e.CancelCommand();
    }
}

在InitializeComponent调用之后,使用以下代码添加此处理程序:

DataObject.AddPastingHandler(textBox1, new DataObjectPastingEventHandler(OnPaste));
上一篇:关于Windows锁屏对WPF渲染的影响


下一篇:在每个特定值后显示一个对话框android