WPF MVVM文本框验证

14

我正在使用MVVM创建WPF应用程序。我有一个文本框,它绑定到ViewModel中类型为double且默认值为0.0的属性。如果我现在在文本框中输入文本值(比如abc),失去焦点后,文本框会被突出显示表示值不正确。但是,用户仍然可以继续单击“提交”以调用ViewModel命令。由于文本框的Text属性绑定到ViewModel中类型为double的属性,因此ViewModel属性包含默认值0.0,我无法找出用户输入的文本。

因此,我无法确定用户是否实际上输入了0的值还是出现了错误的输入。我该如何正确执行此验证?我应该将其绑定到string属性,以便我可以获取输入的文本,并尝试将其解析为double值以查看输入是否正确?还是有更好的方法做到这一点?

<TextBox HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="{Binding DoubleProperty}" VerticalAlignment="Top" Width="120"/>

绑定到字符串属性的解决方案始终有效。所以这取决于你 :) 另一种方法是创建某种行为,使用户只能输入有效值(在您的情况下只有数字)。 - blindmeis
2个回答

23

您可以将验证规则附加到文本框的绑定上,以检查值是否为有效的double类型。这将防止用户能够按下“提交”按钮,除非输入了有效的值,从而消除了您在提交时检查DoubleProperty值是否有效的需求,因为只有在提交按钮启用时它才是有效的。以下是一个简单的示例:

<TextBox HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" VerticalAlignment="Top" Width="120">
        <TextBox.Text>
            <Binding Path="DoubleProperty">
                <Binding.ValidationRules>
                    <validationrules:NumberValidationRule/>
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>
在上面的例子中,您需要定义一个继承自ValidationRule的NumberValidationRule类。以下是一个NumberValidationRule示例。
public class NumberValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        double result = 0.0;
        bool canConvert = double.TryParse(value as string, out result);
        return new ValidationResult(canConvert, "Not a valid double");
    }
}

如果您添加了一个验证规则,那么如果您的ValidationRule类说它不是有效值,文本框将在文本字段上引发错误。

为了防止提交按钮被启用,您可以向其添加一个CanExecute事件,该事件检查WPF窗口是否有效。 如下所示:

<Window.CommandBindings>
    <CommandBinding Command="ApplicationCommands.Save" CanExecute="Save_CanExecute" Executed="Save_Executed"/>
</Window.CommandBindings>

... The rest of your page

<Button Content="Save" HorizontalAlignment="Left" Margin="43,146,0,0" VerticalAlignment="Top" Width="75" Command="ApplicationCommands.Save"/>                            

并且在代码后台执行

private void Save_CanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = IsValid(sender as DependencyObject);
    }

private bool IsValid(DependencyObject obj)
    {            
        return !Validation.GetHasError(obj) && LogicalTreeHelper.GetChildren(obj).OfType<DependencyObject>().All(IsValid);
    }

这里是一个更详细的例子:

WPF中的验证


验证规则有效,当文本框失去焦点时会引发错误。然而,按钮点击仍未被禁用。我需要做什么来防止提交按钮命令被触发? - Fahad
我在我的回答中添加了这些细节。 - kmcnamee
我正在使用MVVM,但是我无法阻止提交按钮的触发。不管怎样,我已经将其标记为答案,我也在VM中验证了最终值,所以关于验证规则的第一部分对我有用。谢谢 :) - Fahad

2
您可以尝试以下解决方案。首先,您应该将DoubleProperty声明为Nullable:
    public double? DoubleProperty { get; set; }

然后创建实现IValueConverter的转换器类。它可以看起来像这样:

 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        double result;
        if(!double.TryParse((string)value, out result))
        {
            return null;
        }

        return result;
    }

最后,您可以使用它:

    xmlns:converter="clr-namespace:[TestApplication]"

<Window.Resources>
    <converter:DoubleToStringConverter x:Key="doubleToStringConverter" />
</Window.Resources>

<TextBox HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="{Binding DoubleProperty, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource doubleToStringConverter}}" VerticalAlignment="Top" Width="120"/>

现在,如果用户输入了错误的值-DoubleProperty将为null。

1
谢谢,这将属性重置为null并清除用户输入的文本(如果无效)。这解决了我识别用户输入是否有效的问题,但是我希望保留先前的值并像以前一样突出显示文本框。我将尝试ValidationRule部分,看看它是否更合适,并且是否按照我想要的方式工作。 - Fahad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接