2011-03-03 17 views
2

パスワードを表示したり非表示にするカスタムパスワードボックスユーザーコントロールを作成しました。同じパスワード文字列プロパティにバインドされたテキストボックスで、標準のパスワードボックスをスワップアウトするだけです。すべて正常に動作しますが、データ検証エラーはバックグラウンドで正しく生成されていますが、これ以上表示されません。ここに私のユーザーコントロールからXAMLだ:Silverlight IDataErrorInfoメッセージがカスタムコントロールのテキストボックスに表示されない

<UserControl x:Class="Controls.EAPPasswordBox" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
mc:Ignorable="d" 
d:DesignHeight="300" d:DesignWidth="400" x:Name="_root"> 

<Grid x:Name="LayoutRoot" Background="White"> 
    <StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Top"> 
     <PasswordBox x:Name="pwdBox" Password="{Binding Password, Mode=TwoWay,ValidatesOnDataErrors=True}" /> 
     <TextBox x:Name="txtBox" Text="{Binding Password, Mode=TwoWay,ValidatesOnDataErrors=True}" /> 
    </StackPanel> 
</Grid> 

ここで私はビューでそれを使用する方法は次のとおりです。親ビューののviewmodelで

<local:EAPPasswordBox x:Name="pwdBox" 
       Grid.Column="1" Grid.Row="0" Grid.ColumnSpan="2" Password="{Binding password,Mode=TwoWay, ValidatesOnDataErrors=True}" ShowText="{Binding showPassword,Mode=TwoWay}"></local:EAPPasswordBox> 

私たちは、このようにIDataErrorInfoを実装:

public string this[string columnName] 
    { 
     get 
     { 
      string Result = ""; 
      switch(columnName.ToLower()) 
      { 
       case "password": 
        { 
         Result = Validatepassword(); 
         break; 
        } 
       case "password2": 
        { 
         Result = Validatepassword2(); 
         break; 
        } 
       default: 
        { 
         Result = this.ValidateStringValue(columnName); 

         break; 
        } 
      } 
      return Result; 
     } 
    } 

カスタムパスワードボックスにテキストを入力すると、検証ロジックはちょうどいいと呼ばれますそれは表示されません。このためにユーザーコントロールを調整する必要がありますか?

編集:ここに私のpasswordboxの背後にあるコードです:

public partial class EAPPasswordBox : UserControl, INotifyPropertyChanged 
{ 
    public bool ShowText 
    { 

     get { return (bool)GetValue(ShowTextProperty); } 
     set { 

      SetValue(ShowTextProperty, value); 
       if (value == true) 
       { 
        this.pwdBox.Visibility = System.Windows.Visibility.Collapsed; 
        this.txtBox.Visibility = System.Windows.Visibility.Visible; 
       } 
       else 
       { 
        this.pwdBox.Visibility = System.Windows.Visibility.Visible; 
        this.txtBox.Visibility = System.Windows.Visibility.Collapsed; 
       } 
     } 

    } 

    public string Password 
    { 
     get { return (string)GetValue(PasswordProperty); } 
     set { SetValue(PasswordProperty, value); } 
    } 

    private Visibility _PwdBoxVisibility; 

    public Visibility PwdBoxVisibility 
    { 
     get { return _PwdBoxVisibility; } 
     set 
     { 
      _PwdBoxVisibility = value; NotifyPropertyChanged("PwdBoxVisibility"); 
     } 
    } 

    private Visibility _TxtBoxVisibility; 

    public Visibility TxtBoxVisibility 
    { 
     get { return _TxtBoxVisibility; } 
     set 
     { 
      _TxtBoxVisibility = value; NotifyPropertyChanged("TxtBoxVisibility"); 
     } 
    } 

    public static readonly DependencyProperty PasswordProperty = 
     DependencyProperty.Register("Password", typeof(string), typeof(EAPPasswordBox), null); 

    public static readonly DependencyProperty ShowTextProperty = 
     DependencyProperty.Register("ShowText", typeof(bool), typeof(EAPPasswordBox), new PropertyMetadata(OnShowTextPropertyChanged)); 

    public EAPPasswordBox() 
    { 
     InitializeComponent(); 
     this.pwdBox.SetBinding(PasswordBox.PasswordProperty, new System.Windows.Data.Binding() { Source = this, Path = new PropertyPath("Password"), Mode = BindingMode.TwoWay,ValidatesOnDataErrors=true }); 
     this.txtBox.SetBinding(TextBox.TextProperty, new System.Windows.Data.Binding() { Source = this, Path = new PropertyPath("Password"), Mode = BindingMode.TwoWay, ValidatesOnDataErrors=true }); 

     this.ShowText = false; 
    } 


    private static void OnShowTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     EAPPasswordBox passwordBox = d as EAPPasswordBox; 

     if (passwordBox != null) 
     { 
      passwordBox.ShowText=(bool)e.NewValue; 
     } 

    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 


} 

第二編集:誰かが私には親ウィンドウのXAMLでユーザーコントロールの結合特性の基本を説明するだろう場合にも/役立つだろうコントロール。私はかなり理解していないなぜusercontrolは、それがxamlを介してそれらにバインドされているので、対応する親ビューviewmodelプロパティのプロパティ変更されたイベントを取得します。

+0

私はそれを解決し、ロードされたイベントのコントロールのtext/pwボックスをビューモデルのプロパティに直接バインドしました。バインドするパスワードプロパティを識別するために、親ビューのxamlからコントロールのプレーンなパブリックプロパティの値を渡します。後で完全な回答を投稿します。 – hoetz

答えて

1

私の解決策は最後です。私は、ユーザーコントロールのDataContextが自動的に親ビューのViewModelであることに気づいたので、Password依存関係プロパティのバインディングを完全にダンプしました。親ビューモデルのパスワードプロパティに設定しなければならない新しいパラメータをコントロールに導入しました。次に、この文字列を使用して、コントロールのロードされたイベントで、テキストボックスとパスワードボックスの手動バインディングを行います。ここに私のコードです:

public partial class EAPPasswordBox : UserControl, INotifyPropertyChanged 
{ 
    public bool ShowText 
    { 

     get { return (bool)GetValue(ShowTextProperty); } 
     set { 

      SetValue(ShowTextProperty, value); 
       if (value == true) 
       { 
        this.pwdBox.Visibility = System.Windows.Visibility.Collapsed; 
        this.txtBox.Visibility = System.Windows.Visibility.Visible; 
       } 
       else 
       { 
        this.pwdBox.Visibility = System.Windows.Visibility.Visible; 
        this.txtBox.Visibility = System.Windows.Visibility.Collapsed; 
       } 
     } 

    } 

    public string PasswordPropertyName { get; set; } 



    private Visibility _PwdBoxVisibility; 

    public Visibility PwdBoxVisibility 
    { 
     get { return _PwdBoxVisibility; } 
     set 
     { 
      _PwdBoxVisibility = value; NotifyPropertyChanged("PwdBoxVisibility"); 
     } 
    } 

    private Visibility _TxtBoxVisibility; 

    public Visibility TxtBoxVisibility 
    { 
     get { return _TxtBoxVisibility; } 
     set 
     { 
      _TxtBoxVisibility = value; NotifyPropertyChanged("TxtBoxVisibility"); 
     } 
    } 


    public static readonly DependencyProperty ShowTextProperty = 
     DependencyProperty.Register("ShowText", typeof(bool), typeof(EAPPasswordBox), new PropertyMetadata(OnShowTextPropertyChanged)); 

    public EAPPasswordBox() 
    { 
     InitializeComponent(); 
     this.ShowText = false; 
    } 


    private static void OnShowTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     EAPPasswordBox passwordBox = d as EAPPasswordBox; 

     if (passwordBox != null) 
     { 
      passwordBox.ShowText=(bool)e.NewValue; 
     } 

    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 

    private void _root_Loaded(object sender, RoutedEventArgs e) 
    { 
     this.pwdBox.SetBinding(PasswordBox.PasswordProperty, new System.Windows.Data.Binding() { Source = this.DataContext, Path = new PropertyPath(PasswordPropertyName), Mode = BindingMode.TwoWay, ValidatesOnDataErrors = true }); 
     this.txtBox.SetBinding(TextBox.TextProperty, new System.Windows.Data.Binding() { Source = this.DataContext, Path = new PropertyPath(PasswordPropertyName), Mode = BindingMode.TwoWay, ValidatesOnDataErrors = true }); 

    } 


} 

ここはコントロールのXAMLです。

<UserControl x:Class="GAB.EAP2011.Controls.EAPPasswordBox" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
mc:Ignorable="d" 
d:DesignHeight="300" d:DesignWidth="400" x:Name="_root" Loaded="_root_Loaded"> 

<Grid x:Name="LayoutRoot" Background="White"> 
    <StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Top"> 
     <PasswordBox x:Name="pwdBox" /> 
     <TextBox x:Name="txtBox" /> 
    </StackPanel> 
</Grid> 

は、ここでそれを使用する方法は次のとおりです。

<local:EAPPasswordBox x:Name="pwdBox" 
       Grid.Column="1" Grid.Row="0" Grid.ColumnSpan="2" PasswordPropertyName="password" ShowText="{Binding showPassword,Mode=TwoWay}"></local:EAPPasswordBox> 

は今、あなたは素敵なパスワード視界スイッチャー制御:)感謝 コメントを得ました!

+0

回答ありがとうございました。私はあなたのものと同じ考えを実装しましたが、まだ私はエラーが発生しています。私はコードの完全なサンプルを送ることができますか? – imdadhusen

+0

+1の私の投票と私もお気に入りとしてマーク。 – imdadhusen

関連する問題