我运行了WPF验证(将ValidationRules
添加到绑定中)并且使用模板我可以创建漂亮的装饰器。那里有很多帖子。
但我找不到在窗口一角的固定位置(例如TextBlock
)显示装饰控件之外的错误消息的方法,例如
我怎么能实现这个目标?我可以将所有验证错误消息绑定到DataContext
(此处为ViewModel)吗?
更新:由于答案我得到了部分工作。验证消息现在显示在另一个标签中。由于所有带有验证规则的文本框都是通过代码动态创建的,因此以这种方式完成绑定:
Binding bindSite = new Binding();
bindSite.Source = this.validationErrorDisplayLabel;
BindingOperations.SetBinding(textBox, Validation.ValidationAdornerSiteProperty, bindSite);
但验证消息仅转发到执行此代码的最后一个文本框的adornersite
。
我在这个小例子中重现了这个问题。
XAML:
<Grid>
<TextBox
Validation.ValidationAdornerSite="{Binding ElementName=ErrorDisplay}"
HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120">
<TextBox.Text>
<Binding>
<Binding.Path>Box1</Binding.Path>
<Binding.ValidationRules>
<local:RuleA />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<TextBox
Validation.ValidationAdornerSite="{Binding ElementName=ErrorDisplay}"
HorizontalAlignment="Left" Height="23" Margin="10,38,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120">
<TextBox.Text>
<Binding>
<Binding.Path>Box2</Binding.Path>
<Binding.ValidationRules>
<local:RuleA />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<TextBlock
x:Name="ErrorDisplay"
Background="AntiqueWhite"
Foreground="Red"
Text="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.ValidationAdornerSiteFor).(Validation.Errors)[0].ErrorContent}"
HorizontalAlignment="Left" Margin="230,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" RenderTransformOrigin="2.218,-4.577" Width="177" Height="51"/>
</Grid>
当值等于字符串RuleA
时,类"A"
会产生验证错误。第二个文本框中的错误显示在TextBlock中,第一个文本框中的错误没有显示(而是使用默认模板并获得红色边框)。
两者如何运作?文本块不需要总结所有错误,但会显示第一个错误。
答案 0 :(得分:6)
您可以将BindingGroup
与Validation.ValidationAdornerSite
和Validation.ValidationAdornerSiteFor
属性结合使用。
This blog post向您展示了如何执行此操作的示例。
<StackPanel x:Name="FormRoot"
Validation.ValidationAdornerSite="{Binding ElementName=ErrorDisplay}">
<FrameworkElement.BindingGroup>
<BindingGroup Name="FormBindingGroup" />
</FrameworkElement.BindingGroup>
<TextBox>
<TextBox.Text>
<Binding BindingGroupName="FormBindingGroup"
UpdateSourceTrigger="LostFocus"
Path="Box1">
<Binding.ValidationRules>
<l:RuleA />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<TextBox>
<TextBox.Text>
<Binding BindingGroupName="FormBindingGroup"
UpdateSourceTrigger="LostFocus"
Path="Box2">
<Binding.ValidationRules>
<l:RuleA />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<ItemsControl x:Name="ErrorDisplay"
Background="AntiqueWhite"
Foreground="Red"
ItemsSource="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.ValidationAdornerSiteFor).(Validation.Errors)}"
DisplayMemberPath="ErrorContent" />
</StackPanel>
要在用户输入时提交值,请将UpdateSourceTrigger
值更改为PropertyChanged
。请注意,在此处使用ValidationAdornerSite
并非绝对必要;您只需将ErrorDisplay
绑定直接指向BindingGroup
的所有者:
ItemsSource="{Binding ElementName=FormRoot, Path=(Validation.Errors)}"
答案 1 :(得分:3)
感谢http://www.scottlogic.com/blog/2008/11/28/using-bindinggroups-for-greater-control-over-input-validation.html我能够使用BindingGroup和没有ValidationAdornerSite来解决这个问题。
<Window x:Class="BindingAndValidation.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BindingAndValidation"
Title="Binding and Validation" Height="110" Width="425"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
>
<Grid x:Name="RootElement">
<Grid.Resources>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<Grid.BindingGroup>
<BindingGroup Name="LocalBindingGroup">
<BindingGroup.ValidationRules>
<local:RuleGroup />
</BindingGroup.ValidationRules>
</BindingGroup>
</Grid.BindingGroup>
<TextBox
HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" LostFocus="TextBox_LostFocus">
<TextBox.Text>
<Binding>
<Binding.Path>Box1</Binding.Path>
<Binding.BindingGroupName>LocalBindingGroup</Binding.BindingGroupName>
<Binding.ValidationRules>
<local:RuleA />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<TextBox
HorizontalAlignment="Left" Height="23" Margin="10,38,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120">
<TextBox.Text>
<Binding>
<Binding.Path>Box2</Binding.Path>
<Binding.BindingGroupName>LocalBindingGroup</Binding.BindingGroupName>
<Binding.ValidationRules>
<local:RuleA />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<ItemsControl ItemsSource="{Binding Path=(Validation.Errors), ElementName=RootElement}" MinWidth="100" MinHeight="16" Margin="230,10,0,0" Background="AntiqueWhite" Foreground="Red">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label Foreground="Red" Content="{Binding Path=ErrorContent}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Content="Button" HorizontalAlignment="Left" Margin="150,0,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click" />
</Grid>
</Window>
只有在您致电CommitEdit
时才会进行验证。如果您希望立即使用它,我可以使用LostFocus
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
this.RootElement.BindingGroup.CommitEdit();
}
当然,对于一个更大的项目,附属财产可能有所帮助。