簡體   English   中英

未顯示密碼箱Validation.ErrorTemplate

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM