我一直很欣赏约什史密斯建立他sample application的方式。 我还试图模仿他的应用程序的ViewModel实现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提到的here类。{{3}}。 除此之外,这是一个很好的解决方案。它不是让我用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"
我确定,这个问题正在发生,因为密码属性已被辅助类扩展。如果我放弃这种方法,我将不得不从IDataErrorInfo实现中删除Password属性,并在登录按钮单击将必须验证它,向用户显示一个消息框。但并非没有妥协的一致性。我不太了解依赖属性;可以有任何解决方法吗?是否会以某种方式更改帮助程序类,让我重新找到红色错误消息?
答案 0 :(得分:4)
我在密码绑定中没有看到ValidatesOnDataErrors=True
,所以也许这就是你的问题。默认情况下,它设置为False
,这意味着绑定不会向UI警告任何验证错误。
那就是说,我认为Password
故意不是DependencyProperty
,因为你真的不应该把密码存储为纯文本。
通常我最终将PasswordBox.Password
(或整个PasswordBox
)作为CommandParameter
传递给我的LoginCommand
,然后它可以获取数据并做任何想做的事情它。通常这意味着对它进行散列或将其与存储的密码的散列进行比较以查看它是否相同。如果登录失败,我会将相关的错误消息写入我的ViewModel中的属性,该属性绑定到登录UI。
<Button Command="{Binding LoginCommand}"
CommandParameter="{Binding ElementName=MyPasswordBox, Path=Password}" />
答案 1 :(得分:0)
不确定这是否是您的问题,但您没有关闭PasswordBox
的默认ErrorTemplate。 (即没有Validation.ErrorTemplate="{x:Null}
)
Validation.Errors
的{{1}}内容,以确保错误实际存在(甚至只是将ItemsControl绑定到它) ?