Сообщение Silverlight IDataErrorInfo не отображается в текстовом поле пользовательского элемента управления - PullRequest
2 голосов
/ 03 марта 2011

Я создал пользовательский элемент управления паролем, который может показывать и скрывать пароль. Он просто заменяет стандартное поле пароля текстовым полем, которое привязано к тому же свойству строки пароля. Все работает нормально, но теперь мои ошибки проверки данных больше не отображаются, хотя они правильно генерируются в фоновом режиме. Вот xaml из моего пользовательского элемента управления:

<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>

Вот как я использую его в представлении:

 <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;
        }
    }

Теперь, когда я ввожу текст в поле ввода пароля, логика проверки вызывается просто отлично, но она не отображается. Должен ли я настроить свой пользовательский контроль для этого?

РЕДАКТИРОВАТЬ: Вот код моего пароля:

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


}

2-е редактирование: Было бы также полезно, если бы кто-то просто объяснил мне основы связывания свойств пользовательских элементов управления в xaml родительского окна / элемента управления. Я не совсем понимаю, почему usercontrol не получает события измененных свойств соответствующих свойств viewmodel родительских представлений, поскольку он привязан к тем через xaml.

1 Ответ

1 голос
/ 10 марта 2011

Вот мое решение, наконец. Поскольку я понял, что 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>

Теперь у вас есть приятный элемент управления переключением видимости пароля :) Комментарии приветствуются!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...