我一直很欣赏 Josh Smith 构建他的示例应用程序的方式。而且我还尝试模拟他的应用程序的 ViewModels 实现 IDataErrorInfo 属性的方式,并通过自定义 DataTemplate 在用户面前呈现错误。这是他用来显示错误的数据模板:
<DataTemplate DataType="{x:Type ValidationError}">
<TextBlock FontSize="10"
FontStyle="Italic"
Foreground="Red"
HorizontalAlignment="Right"
Margin="0,1"
Text="{Binding Path=ErrorContent}"/>
</DataTemplate>
使用此数据模板的工作示例如下:
<TextBox x:Name="txtUsername"
Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2"
Width="300"
Margin="2"
Text="{Binding Path=Username,
ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged}"
Validation.ErrorTemplate="{x:Null}"/>
<ContentPresenter Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2"
Content="{Binding ElementName=txtUsername,
Path=(Validation.Errors).CurrentItem}"/>
文本框的默认 ErrorTemplate(出现在其周围的红色边界)被新的错误模板替换,其中放置在文本框下方的内容呈现器会将错误传达给用户——当然是一个更高级、更优雅的模板。
如果您已经阅读了上面的代码,您可能已经猜到我正在尝试创建一个登录表单。
不幸的是,登录表单需要密码(以及随后的 PasswordBox)。PasswordBox 不提供“密码”作为依赖属性。我不想打破 MVVM 尽可能避免代码落后的准则,所以很想去这里提到的PasswordBoxAssistant类. 否则这是一个很好的解决方案,保存一件事。它不允许我使用 Josh 的数据模板验证密码框。我已经验证了我的 ViewModel 的密码属性不为空。该属性正在得到验证,因为我的“登录”按钮在没有用户填写密码的情况下没有启用。但是,我在此属性验证过程中设置的“输入密码”消息并未由位于 PasswordBox 下方的内容呈现器呈现。代码如下:
<Label Content="Password:" Grid.Column="0" Grid.Row="2" Margin="2" />
<PasswordBox x:Name="PasswordBox"
Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2"
Margin="2"
Validation.ErrorTemplate="{x:Null}"
ff:PasswordBoxAssistant.BindPassword="true"
ff:PasswordBoxAssistant.BoundPassword="{Binding Path=Password,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"/>
<ContentPresenter Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2"
Content="{Binding ElementName=PasswordBox,
Path=(Validation.Errors).CurrentItem}"/>
不用说,上面代码中的 ff 代表命名空间引用:
xmlns:ff="clr-namespace:MyProject.UserViews"
我敢肯定,这个问题正在发生,因为 Password 属性已被助手类扩展。如果我放弃这种方法,我将不得不从 IDataErrorInfo 实现中删除 Password 属性,并且在登录按钮上单击必须验证它,向用户显示一个消息框。但并非不影响一致性。我不太了解依赖属性;有什么解决方法吗?以某种方式更改助手类会让我恢复红色错误消息吗?