2016-10-19 34 views
2

我试图显示PasswordBoxValidation.ErrorTemplate。但是,它没有显示。在同一表单上,我有一个用户名TextBox,并且ErrorTemplate显示正确。未显示Passwordbox Validation.ErrorTemplate

的XAML在datatempalte的PasswordBox:

<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)); 
     } 
    } 
} 
+0

试试 Nathan

+0

@Nathan,感谢您的建议。但是这并没有解决这个问题。 –

+0

您尝试了哪些解决方法以及结果如何?你有没有尝试在InitializeComponent之后的代码中设置DataContext?您是否尝试过构建一个简单的bootleg项目来显示自定义验证错误并逐步将其修改为您当前的代码?您是否尝试过在Validation.HasError中添加触发器以查看是否出现默认验证错误? – Nathan

回答

0

的问题是,该错误是在承载在验证错误发生数据绑定属性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。为了错误传播的目的,我决定将视图模型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属性默认绑定双向:

public static readonly DependencyProperty PasswordProperty = DependencyProperty.Register(
    "SPassword", 
    typeof(SecureString), 
    typeof(PasswordBoxBehaviorBinding), 
    new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); 

否则,请务必设置适当的结合模式。