У меня есть форма с двумя полями пароля - одна, где пользователь вводит пароль, а другой, где пользователь должен повторно ввести этот пароль для подтверждения. Валидация используется для подтверждения того, что оба пароля совпадают - если они делают, кнопка включена, чтобы позволить пользователю перейти:Проверка нескольких элементов управления одновременно в WPF
<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>
Моя проблема заключается в том, что пользователь может изменить пароль в первом поле, и он не заставит второе поле пароля повторить проверку. Например, если первый пароль вводится как «пароль», а пользователь вводит «пароль» во второй блок, проверка проходит и кнопка включается. Если пользователь затем изменит исходное поле пароля на «ПАРОЛЬ», оба окна остаются проверенными - оригинал, потому что нет ограничений на непустой пароль, второй - потому что ничто не заставило проверку обновить.
В моих блоках ввода пароля используется связанное свойство here, чтобы разрешить привязку к паролю. Из-за этого я не могу найти способ получить доступ к нему в коде (поскольку PasswordBox.Password не является свойством зависимостей сам по себе) способом, выраженным в this solution. Или, возможно, он просто не работает для прикрепленных свойств привязка объекта PasswordData и коробки паролей устанавливаются на PasswordData -
P2Box.GetBindingExpression(PasswordBoxAssistant.BoundPassword).UpdateSource();
у меня есть пользовательский класс, который наследует IDataErrorInfo, чтобы для проверки между двумя элементами управления: - код ниже ничего не делать. 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, если это имеет значение.
EDIT:
ОК, так получается, что я неправильно набранный обработчик события в XAML, и решение действительно работает:
private void PasswordChanged(object sender, RoutedEventArgs e)
{
binding.Pass.P1 = ((PasswordBox)sender).Password;
P2Box.GetBindingExpression(PasswordBoxAssistant.BoundPassword).UpdateSource();
}
я должен вручную обновить привязку, поскольку событие срабатывает перед обновлением привязки.
Мне любопытно, существует ли правильный способ XAML, используя правила проверки, IDataErrorInfo или некоторые другие средства для привязки между элементами управления без необходимости подключаться к событиям и вручную обновлять.
+1 Очень хорошо написанный вопрос. – JDB