启用文本框时如何触发新的验证?

Posted

技术标签:

【中文标题】启用文本框时如何触发新的验证?【英文标题】:How to trigger a new validation when a textbox gets enabled? 【发布时间】:2014-10-22 13:15:17 【问题描述】:

在 wpf 对话框窗口中,我有一个复选框,用于启用和禁用文本框。文本框的 ValidatesOnDataErrors 设置为 True。通过 IDataErrorInfo 我只检查这个文本框的值,如果复选框被选中。

我的问题是,如果用户选中该复选框,则没有对文本框执行新的验证,因此我没有看到这个红框表示错误。

这里是一个小示例用于演示:

<Window x:Class="Validation.ValidationWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="ValidationWindow" Height="300" Width="300">
<DockPanel LastChildFill="False">
    <CheckBox DockPanel.Dock="Top" IsChecked="Binding InputAllowed">Input allowed</CheckBox>
    <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
        <Label>InputValue</Label>
        <TextBox Text="Binding InputValue, ValidatesOnDataErrors=True" IsEnabled="Binding InputAllowed" Width="50"/>
    </StackPanel>
    <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
        <Label>InputValue2</Label>
        <TextBox Text="Binding InputValue2, ValidatesOnDataErrors=True" Width="50"/>
    </StackPanel>
    <Button DockPanel.Dock="Bottom" Click="OnOk">Ok</Button>
</DockPanel>
</Window>

后面的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Validation

/// <summary>
/// Interaction logic for ValidationWindow.xaml
/// </summary>
public partial class ValidationWindow : Window, IDataErrorInfo

    public bool InputAllowed
    
        get  return (bool)GetValue(InputAllowedProperty); 
        set  SetValue(InputAllowedProperty, value); 
    
    public static readonly DependencyProperty InputAllowedProperty =
        DependencyProperty.Register("InputAllowed", typeof(bool), typeof(ValidationWindow), new PropertyMetadata(false));

    public int InputValue
    
        get  return (int)GetValue(InputValueProperty); 
        set  SetValue(InputValueProperty, value); 
    
    public static readonly DependencyProperty InputValueProperty =
        DependencyProperty.Register("InputValue", typeof(int), typeof(ValidationWindow), new PropertyMetadata(0));

    public int InputValue2
    
        get  return (int)GetValue(InputValue2Property); 
        set  SetValue(InputValue2Property, value); 
    
    public static readonly DependencyProperty InputValue2Property =
        DependencyProperty.Register("InputValue2", typeof(int), typeof(ValidationWindow), new PropertyMetadata(0));


    public ValidationWindow()
    
        InitializeComponent();
        DataContext = this;
    

    private void OnOk(object sender, RoutedEventArgs e)
    
        string msg = Error;
        if(!string.IsNullOrEmpty(Error))
        
            MessageBox.Show(Error);
            return;
        
        DialogResult = true;
    

    #region IDataErrorInfo Members

    public string Error
    
        get  return ((IDataErrorInfo)this)[null]; 
    

    public string this[string columnName]
    
        get
        
            string msg = string.Empty;

            if(string.IsNullOrEmpty(columnName))
            
                msg += ((IDataErrorInfo)this)["InputValue"];
                msg += ((IDataErrorInfo)this)["InputValue2"];
            
            else
            
                switch(columnName)
                
                case "InputValue":
                    if(InputAllowed)
                    
                        if(InputValue <= 0)
                        
                            msg += "InputValue must be greater that 0!";
                        
                    
                    break;
                case "InputValue2":
                    if(InputValue2 <= 0)
                    
                        msg += "InputValue2 must be greater that 0!";
                    
                    break;
                
            

            return msg;
        
    

    #endregion



【问题讨论】:

我尝试了您的代码,验证对我来说非常有效 - 无论是打开还是关闭复选框,如果输入不是数字,我都会得到红色边框。 @tube-builder 它对我不起作用。另外这里的条件是不是数字,如果是not positive,则认为是无效的。尝试选中复选框,您会看到第一个文本框没有任何红色边框,尽管单击按钮会正确显示错误消息。我们必须更改文本框的值(例如删除当前的 0 值并重新键入该值)以使其按预期工作。 【参考方案1】:

我们一直在使用它来在以编程方式更改文本后强制验证,如果您调用它以响应您的复选框的事件,它应该也可以工作:

var binding = someTextBox.GetBindingExpression( TextBox.TextProperty );
if( binding == null )
  return;
binding.UpdateSource();

【讨论】:

你是对的。如果我将此代码放在复选框的 Checked 和 Unchecked 事件中,它会按预期工作。但这不是很方便,如果您有具有多个此类结构的复杂窗口。我希望有一种更简单的方法,例如当 IsEnabled 更改时触发验证的样式(或我忽略的标志)。 这有点超出这个问题的范围,但我很确定您可以使用 DependencyProperty 创建自定义属性,以便在 xaml 中您可以执行&lt;TextBox behav:TriggerValidation.Source="myCheckbox", behav:TriggerValidation.Event="checked"/&gt; 之类的操作。这里有很多关于 SO 的例子,至少那是我得到很多 DependencyProperties 的地方:] 有趣。您能否提供有关如何执行此操作的更多信息? 我建议您从 ACB 的源代码开始:marlongrech.wordpress.com/2008/12/13/… 快速浏览一下,因为它允许您使任何事件调用任意命令,所以修改它并不是一个很大的步骤以便它在我的答案中调用代码而不是任意命令。您必须添加一个属性才能获取文本框。如果不成功,我建议您为此发布一个不同的问题。【参考方案2】:

与 stijn 的解决方案没有实际区别,但因为我们都有点懒:

public static class DependencyPropertyExtensions

    public static bool UpdateSource(this FrameworkElement source, DependencyProperty property)
    
        var binding = source.GetBindingExpression(property);
        if (binding != null)
        
            binding.UpdateSource();
            return true;
        

        return false;
    

【讨论】:

以上是关于启用文本框时如何触发新的验证?的主要内容,如果未能解决你的问题,请参考以下文章

填写值后在输入文本框时未触发提交。在 IE 中

网格视图验证

单击文本框时会触发哪个 javascript 事件?

text 键入文本框时如何关闭自动更正?

基于动态选择启用文本框并对文本框应用验证

在 jQuery 中填充文本框时执行 javascript 函数?