我正在尝试显示 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);
}
}
}
}
}
我在基本 View 模型中实现了 INotifyDataError
接口(interface)。
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
上引发的托管发生验证错误的数据绑定(bind)属性。在你的情况下 <behavior:PasswordBoxBehaviorBinding SPassword="{Binding Path=Password, ValidatesOnNotifyDataErrors=True}" />
意味着,您可以在行为中读取您的错误。
在这一点上,我也想反对你对 SPassword
的绑定(bind)所做的奇怪的黑客攻击。 .只需正常设置值即可:
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
从附加行为到主机控件以一种优雅的方式。所以基本上,您的选择是以某种方式将行为中的错误链接绑定(bind)到密码框,或者创建一个额外的绑定(bind)到您的属性,因为此绑定(bind)将使用相同的验证机制并因此设置 Validation.Errors
在 PasswordBox
上.我决定绑定(bind) View 模型 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>
请注意,我从行为中的绑定(bind)中删除了绑定(bind)错误验证,因为它无论如何都没有用,我为 Tag
添加了绑定(bind)错误验证。绑定(bind)。
还有一件事:我改变了 SPassword
默认情况下双向绑定(bind)的属性:
public static readonly DependencyProperty PasswordProperty = DependencyProperty.Register(
"SPassword",
typeof(SecureString),
typeof(PasswordBoxBehaviorBinding),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
否则,请确保正确设置绑定(bind)模式。
关于c# - Passwordbox Validation.ErrorTemplate 未显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40135404/