WPF ValidationRule和Validation.Error不会引发事件

时间:2011-05-03 08:35:33

标签: wpf

这些代码有什么问题,Validation.Error永远不会被触发,而我将 NotifyOnValidationError 属性设置为 True 。因此,方法“Grid_Error(object sender,ValidationErrorEventArgs e)”永远不会被执行,但我不知道为什么:(

<Window xmlns:my="clr-namespace:WpfDigitalClock;assembly=WpfDigitalClock"  x:Class="WpfApplication1.MainWindow"
    xmlns:local="clr-namespace:WpfApplication1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <local:Names x:Key="MyNames" />
</Window.Resources>
<Grid Validation.Error="Grid_Error">
    <TextBox Height="21" Margin="12,62,0,0" Name="TextBox1" VerticalAlignment="Top" HorizontalAlignment="Left" Width="120">
        <TextBox.Text>
            <Binding Source="{StaticResource MyNames}" Path="FirstName" NotifyOnValidationError="True">
                <Binding.ValidationRules>
                    <local:StringValidator />
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>
    <TextBox Height="21" HorizontalAlignment="Right" Margin="0,62,12,0" Name="TextBox2" VerticalAlignment="Top" Width="120" >
        <TextBox.Text>
            <Binding Source="{StaticResource MyNames}" Path="LastName" NotifyOnValidationError="True">
                <Binding.ValidationRules>
                    <local:StringValidator />
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>
    <Button HorizontalAlignment="Left" Margin="35,122,0,116" Name="Button1" Width="75" Click="Button1_Click">Back</Button>
    <Button HorizontalAlignment="Right" Margin="0,122,34,117" Name="Button2" Width="75" Click="Button2_Click">Forward</Button>
    <Button Height="22" Margin="101,0,101,56" Name="Button3" VerticalAlignment="Bottom" Click="Button3_Click">Add</Button>
</Grid>

Window1.xaml.cs文件中的

public class StringValidator : ValidationRule
{
    public override ValidationResult Validate(object value,
       System.Globalization.CultureInfo cultureinfo)
    {
        string aString = value.ToString();
        if (aString == "")
            return new ValidationResult(false, "String cannot be null");
        return new ValidationResult(true, null);
    }
}

private void Grid_Error(object sender, ValidationErrorEventArgs e)
{
    if(e.Action == ValidationErrorEventAction.Added) 
        MessageBox.Show(e.Error.ErrorContent.ToString());
}

感谢您的帮助!

编辑:

这是我的姓名类:

class Names : ObservableCollection<Name>
{
    public Names ()
    {
        Name aName = new Name("FirstName " + (this.Count +1).ToString(),
            "LastName " + (this.Count + 1).ToString());

        this.Add(aName);
    }
}

这是我的名字课:

class Name : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private string _firstName;
    private string _lastName;


    public Name(string fName,  string lName)
    {
        _firstName = fName;
        _lastName = lName;
    }

    public string FirstName 
    { 
        get
        {
            return _firstName;
        }
        set
        {
            _firstName = value; 
            PropertyChanged(this, new PropertyChangedEventArgs("FirstName"));
        }
    }
    public string LastName 
    {
        get
        {
            return _lastName;
        }
        set
        {
            _lastName = value; 
            PropertyChanged(this, new PropertyChangedEventArgs("LastName"));
        }
    }
}

3 个答案:

答案 0 :(得分:3)

应用程序无法修改此集合的内容。有关如何使用此附加属性的示例,请参阅示例部分。

WPF数据绑定模型使您可以将ValidationRules与Binding对象相关联。在调用转换器之前,在绑定目标到绑定源值传输期间进行验证。以下描述了验证过程:

1.当值从目标属性传输到源属性时,数据绑定引擎首先删除可能已添加到绑定元素的Validation.Errors附加属性的任何ValidationError。然后它检查是否有为该Binding定义的任何自定义ValidationRules,在这种情况下,它会调用每个ValidationRules上的Validate方法,直到其中一个遇到错误或直到所有这些都通过。

2.一旦有自定义规则未通过,绑定引擎就会创建一个ValidationError对象并将其添加到绑定元素的Validation.Errors集合中。当Validation.Errors不为空时,元素的Validation.HasError附加属性设置为true。此外,如果Binding的NotifyOnValidationError属性设置为true,则绑定引擎会在元素上引发Validation.Error附加事件。

3.如果所有规则都通过,绑定引擎会调用转换器(如果存在)。

4.如果转换器通过,绑定引擎将调用source属性的setter。

5.如果绑定具有与之关联的ExceptionValidationRule,则在步骤期间抛出异常 4,绑定引擎检查是否有UpdateSourceExceptionFilter。您可以选择使用UpdateSourceExceptionFilter回调来提供处理异常的自定义处理程序。如果未在Binding上指定UpdateSourceExceptionFilter,则绑定引擎会创建带有异常的ValidationError,并将其添加到绑定元素的Validation.Errors集合中。

另请注意,在任一方向(目标到源或源到目标)的有效值传输都会清除Validation.Errors附加属性。

有关MultiBinding方案中此属性的行为的信息,请参阅ValidationError。

答案 1 :(得分:2)

根据您的评论,我会得出结论ValidationRule不会返回错误,因此不会触发错误事件。尝试使用调试器逐步执行Validation方法。

此外,验证仅在通常在LostFocus上发生的TextBox中的源更新时执行。

编辑: MyNames是一个集合,它没有您尝试绑定的属性,“输出”窗口中应该存在绑定错误。

如果要绑定到第一个元素,则需要将路径更改为类似[0].LastName的内容,以用于姓氏绑定。

答案 2 :(得分:0)

你的Names类是否实现了INotifyPropertyChanged?

在文件的代码隐藏文件中,将datacontext设置为this。将您的Names对象公开为属性,看看是否有效。我不习惯绑定到窗口中的静态资源。