[英]Passwordbox Validation.ErrorTemplate not displayed
我正在嘗試顯示PasswordBox
Validation.ErrorTemplate
。 但是,它沒有顯示。 在同一表格上,我有一個用戶名TextBox
,並且ErrorTemplate
正確顯示。
數據臨時目錄中的PasswordBox的Xaml:
<PasswordBox Grid.Row="3" DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType=ContentControl}}">
<PasswordBox.Style>
<Style>
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<TextBlock DockPanel.Dock="Right" Foreground="Red" FontSize="14" FontWeight="Bold">*</TextBlock>
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder/>
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</PasswordBox.Style>
<i:Interaction.Behaviors>
<behavior:PasswordBoxBehaviorBinding SPassword="{Binding Path=Password, ValidatesOnNotifyDataErrors=True}" />
</i:Interaction.Behaviors>
</PasswordBox>
以下是我正在使用的附加屬性。
public class PasswordBoxBehaviorBinding : Behavior<PasswordBox>
{
public SecureString SPassword
{
get { return (SecureString)GetValue(PasswordProperty); }
set { SetValue(PasswordProperty, value); }
}
public static readonly DependencyProperty PasswordProperty
= DependencyProperty.Register(
"SPassword",
typeof(SecureString),
typeof(PasswordBoxBehaviorBinding),
new PropertyMetadata(null));
protected override void OnAttached()
{
AssociatedObject.PasswordChanged += AssociatedObject_PasswordChanged;
base.OnAttached();
}
protected override void OnDetaching()
{
AssociatedObject.PasswordChanged += AssociatedObject_PasswordChanged;
base.OnDetaching();
}
private void AssociatedObject_PasswordChanged(object sender, RoutedEventArgs e)
{
var binding = BindingOperations.GetBindingExpression(this, PasswordProperty);
if (binding != null)
{
if (binding.ResolvedSource != null)
{
PropertyInfo property = binding.ResolvedSource.GetType()
.GetProperty(binding.ParentBinding.Path.Path);
if (property != null)
{
property.SetValue(binding.ResolvedSource, AssociatedObject.SecurePassword);
}
}
}
}
}
我在基本viewmodel中實現了INotifyDataError
接口。
public class ViewModelBase : BindableBase, INotifyDataErrorInfo
{
private IDictionary<string, List<string>> errors
= new Dictionary<string, List<string>>();
public bool HasErrors
{
get
{
return this.errors.Count > 0;
}
}
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public IEnumerable GetErrors(string propertyName)
{
if ( this.errors.ContainsKey(propertyName) )
{
return this.errors[propertyName];
}
return null;
}
public void AddError(string propertyName, string error)
{
this.errors[propertyName] = new List<string> { error };
this.RaiseErrorsChanged(propertyName);
}
public void RemoveError(string propertyName)
{
if (this.errors.ContainsKey(propertyName))
{
this.errors.Remove(propertyName);
}
this.RaiseErrorsChanged(propertyName);
}
private void RaiseErrorsChanged(string propertyName)
{
if (this.ErrorsChanged != null)
{
this.ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
}
}
}
問題是,在托管發生錯誤的數據綁定屬性的DependencyObject
上引發了錯誤。 在您的情況下, <behavior:PasswordBoxBehaviorBinding SPassword="{Binding Path=Password, ValidatesOnNotifyDataErrors=True}" />
意味着您可以讀取行為內的錯誤。
那時,我還想建議您不要對SPassword
綁定進行奇怪的破解。 只需正常設置值即可:
private void AssociatedObject_PasswordChanged(object sender, System.Windows.RoutedEventArgs e)
{
SPassword = AssociatedObject.SecurePassword;
// use debugger to verify, that the validation errors exist. Otherwise, no need for the following line of code
var behaviorErrors = Validation.GetErrors(this);
}
不幸的是,我還沒有找到如何以一種優雅的方式將Validation.Errors
從附加的行為提升到宿主控件。 因此,基本上,您的選擇是以某種方式將錯誤從行為鏈式綁定到密碼盒,或為屬性創建額外的綁定,因為此綁定將使用相同的驗證機制,從而在PasswordBox
上設置Validation.Errors
。 我決定將viewmodel Password
綁定到PasswordBox.Tag
以便進行錯誤傳播。
<PasswordBox Width="200" Height="100" Tag="{Binding Password,ValidatesOnNotifyDataErrors=True,Mode=OneWay}">
<i:Interaction.Behaviors>
<behavior:PasswordBoxBehaviorBinding SPassword="{Binding Password}"/>
</i:Interaction.Behaviors>
</PasswordBox>
請注意,我從行為上的綁定中刪除了綁定錯誤驗證,因為無論如何它都沒有用,並且我為Tag
綁定添加了綁定錯誤驗證。
還有一件事:默認情況下,我將SPassword
屬性更改為SPassword
綁定:
public static readonly DependencyProperty PasswordProperty = DependencyProperty.Register(
"SPassword",
typeof(SecureString),
typeof(PasswordBoxBehaviorBinding),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
否則,請確保正確設置綁定模式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.