WPF验证结果弹出窗口

时间:2011-01-04 17:45:43

标签: wpf validation popup binding

我正在尝试在几个文本框上实现WPF验证。我希望能够以比工具提示更明显的东西向用户显示验证错误,但比对话框或消息框更微妙。我决定使用Popup类,而不是一些内置的文本框来显示错误,因为有许多不同的字段需要以这种方式进行验证,我希望反馈“附加”到相关字段。

我遇到的问题是Popup的子TextBox与附加的TextBox(Validation.Errors)属性的绑定没有足够积极地更新。一旦出现Error对象,就会更新并显示文本(即“请输入名称。”表示空字段)但如果错误发生更改(即用户输入无效文本),弹出窗口中的消息将保持不变...直到/除非他们输入有效输入,此时弹出窗口会根据需要消失。

我已经完成了一些调试,并且我发现在正确调用验证规则并返回正确结果的同时,Popup的转换器仅在创建初始错误时调用。我想我感到困惑的是,为什么Popup只有在验证状态从“无错误”变为“某些错误”时才会更新,可以这么说。有没有人知道强制更改Validation.Errors的方法会反映在我的Popup的TextBox.Text中?

这是我写的一个xaml例子。

<TextBox Name="MyTextBox">
    <TextBox.Text>
        <Binding Path="MyText" UpdateSourceTrigger="PropertyChanged" >
            <Binding.ValidationRules>
                <local:MyTextBoxValidationRule />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>
<Popup Name="MyPopup" IsOpen="{Binding ElementName=MyTextBox, 
    Path=(Validation.HasError), Mode=OneWay}">
    <Border BorderThickness="1" BorderBrush="Red" Background="White">
        <TextBlock Foreground="Red" Margin="5 5 5 5" 
            Text="{Binding ElementName=MyTextBox, Path=(Validation.Errors), 
            Converter={StaticResource errorsToMessageConverter}}"/>
    </Border>
</Popup>

2 个答案:

答案 0 :(得分:1)

我能够找到妥协方案。我更改了Popup的TextBlock上的绑定,如下所示:

<TextBlock Name="MyPopupTextBox" Foreground="Red" Margin="5 5 5 5" 
    Text="{Binding ElementName=MyTextBox, Path=(Validation.Errors)[0].ErrorContent, 
    UpdateSourceTrigger=PropertyChanged, Mode=OneWay, NotifyOnValidationError=True, 
    NotifyOnSourceUpdated=True, ValidatesOnExceptions=True}"/>

答案 1 :(得分:0)

原始问题是绑定到集合时的典型问题:只要您的集合在结构上没有变化(插入/删除/清除),绑定就不会看到任何更新的原因。因此,如果集合中只有一个项目会更改某些属性,则不会导致绑定更新。

您已经通过绑定到此集合中的元素来解决此问题,这样就可以在绑定中观察到已更改属性的完整路径(ErrorContent)。

绑定(Validation.Errors)[0]的问题在于,如果Error-Collection为空,它会引发IndexOutOfRange-Exceptions(不抛出,但 )。

此主题讨论了该异常,并且还包含一个适用于我的解决方法: http://social.msdn.microsoft.com/forums/en/wpf/thread/1c6cd214-abce-4a8b-a919-0726dd81461a/ 只需将(Validation.Errors)[0].ErrorContent替换为(Validation.Errors).CurrentItem.ErrorContent即可。