WPF中文本框的条件验证规则?

bmt*_*033 3 c# validation wpf

我有一个WPF应用程序,其UI包含一个复选框和一个文本框.复选框和文本框绑定到业务对象上的属性.我一直在使用验证规则来验证用户输入,并且在大多数情况下,它们非常简单(检查值不为空/空,检查值是否在某个范围内等).FWIW,这是我现有的XAML:

<StackPanel>
    <CheckBox x:Name="requirePinNumberCheckBox" IsChecked="{Binding Path=RequirePinNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">Require PIN number</CheckBox>
    <TextBox x:Name="pinNumberTextBox" Style="{StaticResource textBoxInError}" PreviewTextInput="pinNumberTextBox_PreviewTextInput">
        <TextBox.Text>
            <Binding Path="PinNumber" Mode="TwoWay" UpdateSourceTrigger="LostFocus">
                <Binding.ValidationRules>
                    <local:PinNumberValidationRule ValidationStep="RawProposedValue"/>
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)

我对文本框的验证规则很简单:

public class PinNumberValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        // make sure that the PIN number isn't blank
        if (string.IsNullOrEmpty(value.ToString()))
        {
            return new ValidationResult(false, "PIN number cannot be blank.");
        }
        else
        {
            return new ValidationResult(true, null);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

与我的大多数其他验证方案不同,文本框的ValidationRule 在选中复选框时应用(或者更确切地说,当复选框绑定的布尔属性设置为TRUE时).谁能告诉我如何实现这样的东西?谢谢!

小智 8

您应该将验证逻辑从UI(ValidationRule)移开,并考虑IDataErrorInfo在ViewModel中实现.

这篇文章是一个好的开始.

然后你可以做这样的事情:

<StackPanel>
    <CheckBox x:Name="requirePinNumberCheckBox" IsChecked="{Binding Path=RequirePinNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">Require PIN number</CheckBox>
    <TextBox x:Name="pinNumberTextBox" 
             PreviewTextInput="pinNumberTextBox_PreviewTextInput"
             Text="{Binding PinNumber, ValidatesOnDataErrors=True}"
             ToolTip="{Binding (Validation.Errors).CurrentItem.ErrorContent, RelativeSource={RelativeSource Self}}" />
</StackPanel>
Run Code Online (Sandbox Code Playgroud)
   public class ViewModel : IDataErrorInfo, INotifyPropertyChanged
    {
            private bool _requirePinNumber;
            public bool RequirePinNumber
            {
                get
                {
                    return this._requirePinNumber;
                }
                set
                {
                    this._requirePinNumber = value;
                    if (this.PropertyChanged != null)
                    {
                        this.PropertyChanged(this, new PropertyChangedEventArgs("RequirePinNumber"));
                        this.PropertyChanged(this, new PropertyChangedEventArgs("PinNumber"));
                    }
                }
            }

            private string _pinNumber;
            public string PinNumber 
            { 
                get
                {
                    return this._pinNumber;
                }
                set
                {
                    this._pinNumber = value;
                    if (this.PropertyChanged != null)
                    {
                        this.PropertyChanged(this, new PropertyChangedEventArgs("PinNumber"));
                    }
                }
            }

            public string Error
            {
                get 
                { 
                    throw new NotImplementedException(); 
                }
            }

            public string this[string columnName]
            {
                get 
                {
                    if (columnName == "PinNumber") 
                    {
                        if (this.RequirePinNumber && string.IsNullOrEmpty(this.PinNumber))
                        {
                            return "PIN number cannot be blank.";
                        }
                    }
                    return string.Empty;
                }
            }

            public event PropertyChangedEventHandler PropertyChanged;
        }
Run Code Online (Sandbox Code Playgroud)