ユーザーがパスワードを入力する場所と、ユーザーが確認のためにそのパスワードを再入力する必要がある場所の 2 つのパスワード フィールドを持つフォームがあります。検証は、両方のパスワードが一致することを確認するために使用されます。一致する場合、ボタンが有効になり、ユーザーは続行できます。
<PasswordBox Name="P1Box" src:PasswordBoxAssistant.BindPassword="True">
<src:PasswordBoxAssistant.BoundPassword>
<Binding Source="{StaticResource mybinding}" Path="Password.P1" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay">
<Binding.ValidationRules>
<DataErrorValidationRule ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</src:PasswordBoxAssistant.BoundPassword>
</PasswordBox>
ボタンのスタイル:
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=P1Box, Path=(Validation.HasError)}" Value="false"/>
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="true"/>
</MultiDataTrigger>
</Style.Triggers>
私の問題は、ユーザーが最初のボックスでパスワードを変更でき、2 番目のパスワード ボックスの再検証を強制しないことです。たとえば、最初のパスワードが "password" として入力され、ユーザーが 2 番目のボックスに "password" を入力すると、検証が成功し、ボタンが有効になります。その後、ユーザーが元のパスワード ボックスを "PASSWORD" に変更すると、両方のボックスが検証されたままになります。元のボックスは空でないパスワードに制約がないため、2 つ目は検証を強制的に更新するものがないためです。
私のパスワード ボックスは、ここで概説されている添付プロパティを使用して、パスワードへのバインドを許可します。このため、コード ビハインドでアクセスする方法を見つけることができません (PasswordBox.Password 自体は依存関係プロパティではないため)、このソリューションで表現されている方法で。または、添付されたプロパティでは機能しない可能性があります - 以下のコードは何もしませんでした:
P2Box.GetBindingExpression(PasswordBoxAssistant.BoundPassword).UpdateSource();
IDataErrorInfo を継承して 2 つのコントロール間の検証を可能にするカスタム クラスがあります。バインディングは PasswordData オブジェクトであり、パスワード ボックスは PasswordData.P1 と PasswordData.P2 に設定されています。
public class PasswordData : IDataErrorInfo
{
public string P1 { get; set; }
public string P2 { get; set; }
public string Error { get { return string.Empty; } }
public string this[string propertyName]
{
get
{
string ret;
if (propertyName == "P1")
{
if (P1 == null || P1 == "")
ret = "Password cannot be null or empty.";
else
ret = "";
}
else if (propertyName == "P2")
{
if (P2 == null || P2 == "")
ret = "Password cannot be null or empty.";
else if (P2 != P1)
ret = "The passwords do not match.";
else
ret = "";
}
return ret;
}
}
}
PasswordChanged イベント中にホップして、新しい PasswordData を作成し、バインディングを再割り当てしようとしました。これで検証の問題は解決しますが、パスワードボックスのキャレットは常に先頭にあり、入力されたデータが台無しになります。
xaml のみのソリューションが必要ですが、コード ビハインドは完全に受け入れられます。それが重要な場合、私は.Net 4.0を使用しています。
編集:
さて、xaml でイベント ハンドラーの入力を間違えたことがわかりました。解決策は実際に機能します。
private void PasswordChanged(object sender, RoutedEventArgs e)
{
binding.Pass.P1 = ((PasswordBox)sender).Password;
P2Box.GetBindingExpression(PasswordBoxAssistant.BoundPassword).UpdateSource();
}
バインディングが更新される前にイベントが発生するため、バインディングを手動で更新する必要があります。
イベントにフックして手動で更新することなく、検証ルール、IDataErrorInfo、またはその他の手段を使用してコントロール間のバインドを行う適切な XAML のみの方法があるかどうか、私は興味があります。