Проверка выполнена, но красная граница не отображается с пользовательским элементом управления в Silverlight 4 - PullRequest
2 голосов
/ 29 февраля 2012

Я создал пользовательский элемент управления, который содержит TextBox и PasswordBox. Я также привязываю TextBox к UserName и PassowrdBox. Имя пользователя определено в моем классе LoginViewModel с атрибутом [Обязательный]. Теперь мой курсор уходит из TextBox без ввода какого-либо значения, после чего свойство UserName сгорает Свойство изменено, уведомление (INotifyPropertyChanged), но доза не помечает мое текстовое поле (которое находится внутри пользовательского элемента управления) красной рамкой.

Ниже приведен код моего пользовательского элемента управления.

RestrictedBox.xaml

<Grid x:Name="LayoutRoot" Background="Transparent" Margin="0" >
        <TextBox x:Name="txtTextBox" HorizontalAlignment="Stretch" Height="25" />
        <PasswordBox x:Name="txtPasswordBox" HorizontalAlignment="Stretch" Height="25" />
</Grid>

RestrictedBox.xaml.cs

public partial class RestrictedBox : UserControl
    {
        #region Properties
        public string Value
        {
            get { return (string)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }
        public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(RestrictedBox), new PropertyMetadata("", ValueChanged));
        private static void ValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
        }
        public bool Updateable
        {
            get { return (bool)GetValue(UpdateableProperty); }
            set { SetValue(UpdateableProperty, value); }
        }
        public static readonly DependencyProperty UpdateableProperty = DependencyProperty.Register("Updateable", typeof(bool), typeof(RestrictedBox), new PropertyMetadata(UpdateableChanged));
        private static void UpdateableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
        }
        public bool Redactable
        {
            get { return (bool)GetValue(RedactableProperty); }
            set { SetValue(RedactableProperty, value); }
        }
        public static readonly DependencyProperty RedactableProperty = DependencyProperty.Register("Redactable", typeof(bool), typeof(RestrictedBox), new PropertyMetadata(RedactableChanged));
        private static void RedactableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
        }
        #endregion
        #region Constructors
        public RestrictedBox()
        {
            InitializeComponent();
            txtTextBox.SetBinding(TextBox.TextProperty, new Binding { Source = this, Path = new PropertyPath("Value"), Mode = BindingMode.TwoWay});
            txtTextBox.SetBinding(TextBox.VisibilityProperty, new Binding("Redactable") { Source = this, Converter = new BoolToVisibilityConverterReverse() });
            txtPasswordBox.SetBinding(PasswordBox.PasswordProperty, new Binding { Source = this, Path = new PropertyPath("Value"), Mode = BindingMode.TwoWay });
            txtPasswordBox.SetBinding(TextBox.VisibilityProperty, new Binding("Redactable") { Source = this, Converter = new BoolToVisibilityConverter() });
       }
        #endregion
    }

Ниже приведен код, где я использовал свой пользовательский элемент управления

LoginView.xaml

<Control:RestrictedBox x:Name="UserName" VerticalAlignment="Top" TabIndex="2" Grid.Row="1"  Grid.Column="1" HorizontalAlignment="Stretch" Height="40" Value="{Binding Path=LoginModelValue.UserName, Mode=TwoWay, ValidatesOnNotifyDataErrors=True, ValidatesOnExceptions=True,
 ValidatesOnDataErrors=True, NotifyOnValidationError=True}" Validatevalue:UpdateSourceTriggerHelper.UpdateSourceTrigger="True" Redactable="True" Updateable="True"  />

LoginView.xaml.cs

[Export(typeof(LoginView))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public partial class LoginView : UserControl, IPageTitle
    {
        #region Constuctors
        public LoginView()
        {
            InitializeComponent();
        }
        [Import]
        public LoginViewModel ViewModel
        {
            get {return this.DataContext as LoginViewModel;}            
            set { DataContext = value; }
        }
        #endregion
    }

LoginViewModel.cs

 [Export]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class LoginViewModel : INotifyPropertyChanged, IRegionMemberLifetime
    {
        private LoginModel _LoginModelValue;
        public LoginModel LoginModelValue
        {
            get { return _LoginModelValue; }
            set
            {
                _LoginModelValue = value;
                OnPropertyChanged("LoginModelValue");
            }
        }
        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged = delegate { };
        private void OnPropertyChanged(string propertyName)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        void LoginModelValue_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (LoginModelValue.IsValidObject())
            {
                LoginCommand.RaiseCanExecuteChanged();
                IsEnabled = LoginModelValue.IsValidObject();
                SetIncorrectLogin(!IsEnabled);
            }
        }
        #endregion
    }

Кто-нибудь может понять, почему я не окружаю красную рамку моим TextBox, который находится внутри моего пользовательского элемента управления?

Любая помощь, предложения и комментарии будут высоко оценены!

Спасибо

Imdadhusen

Ответы [ 2 ]

1 голос
/ 02 марта 2012

Теперь я решил проблему, используя следующий код. Я заменил следующую строку

txtTextBox.SetBinding(TextBox.VisibilityProperty, new Binding("Redactable") { Source = this, Converter = new BoolToVisibilityConverterReverse() });

на

 this.MapBinding(RestrictedControl.ValueProperty, txtTextBox, TextBox.TextProperty);

и добавил следующий код.вот и все.

namespace QSys.Library.Helpers
{
    public static class FrameworkElementExtension
    {
        public static void MapBinding(this FrameworkElement element, DependencyProperty firstProperty, FrameworkElement targetElement, DependencyProperty secondProperty)
        {
            BindingExpression firstExpression = element.GetBindingExpression(firstProperty);
            if (firstExpression != null && firstExpression.ParentBinding != null)
            {
                targetElement.SetBinding(secondProperty, firstExpression.ParentBinding);
            }
        }
    }
}

Я особенно благодарю всех, кто искал это.и я также очень благодарен Ракешу Гуниджану (http://www.codeproject.com/Articles/293302/Silverlight-user-control-validation) как объяснить очень ясно.

Спасибо,

Imdadhusen

1 голос
/ 01 марта 2012

Как я уже сказал, проверка работает только для одной привязки и не наследуется последующими привязками, как в вашем случае.

Самый простой способ - добавить аннотацию Required непосредственно к свойству Value вашего элемента управления и еще раз проверить его:

[Required]
public string Value
{
    get { return (string)GetValue(ValueProperty); }
    set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(RestrictedBox), new PropertyMetadata("", ValueChanged));
private static void ValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var rb = d as RestrictedBox;
    Validator.ValidateProperty(rb.Value, new ValidationContext(rb, null, null) { MemberName = "Value" });
}

И добавьте атрибут ValidatesOnExceptions к своим привязкам, чтобы проверка работала:

txtTextBox.SetBinding(TextBox.TextProperty, new Binding { Source = this, Path = new PropertyPath("Value"), Mode = BindingMode.TwoWay, 
    ValidatesOnExceptions = true });
//...
txtPasswordBox.SetBinding(PasswordBox.PasswordProperty, new Binding { Source = this, Path = new PropertyPath("Value"), Mode = BindingMode.TwoWay, 
    ValidatesOnExceptions = true });
//...

Другой способ: удалить все свойства и привязать элемент управления RestrictedBox непосредственно к вашей модели представления.

<TextBox x:Name="txtTextBox" HorizontalAlignment="Stretch" Height="25" 
        Text="{Binding LoginModelValue.UserName, Mode=TwoWay, ValidatesOnExceptions=True}" />
<PasswordBox x:Name="txtPasswordBox" HorizontalAlignment="Stretch" Height="25" 
            Password="{Binding LoginModelValue.UserName, Mode=TwoWay, ValidatesOnExceptions=True}" />

Эти решения кажутся далеко не идеальными, но на самом деле проверка с помощью аннотаций данных не является хорошей по своему замыслу. Я бы порекомендовал использовать интерфейс INotifyDataErrorInfo.

...