验证已触发,但 Silverlight 4 中的用户控件未出现红色边框

标签 validation data-binding mvvm silverlight-4.0 user-controls

我创建了包含 TextBox 和 PassowrdBox 的自定义用户控件。我还将 TextBox 绑定(bind)到 UserName 和 PassowrdBox。 UserName 在我的 LoginViewModel 类中使用 [Required] 属性进行定义。现在我的光标从 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
    }

任何人都可以知道为什么我的自定义用户控件内的文本框没有包围红色边框吗?

任何帮助、建议和评论将不胜感激!

谢谢

伊姆达胡森

最佳答案

正如我已经说过的,验证仅适用于一个绑定(bind),并且不会像您的情况那样被后续绑定(bind)继承。

最简单的方法是将 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 属性添加到您的绑定(bind)中,以便验证有效:

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 控件直接绑定(bind)到 View 模型。

<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 接口(interface)。

关于验证已触发,但 Silverlight 4 中的用户控件未出现红色边框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9498047/

相关文章:

wpf - 尽管样式,ComboBoxItem 继续抛出绑定(bind)错误

c# - 绑定(bind)到集合的 View 并在 WPF 中调用 ToString()

c# - WPF ListBox 多项选择不会在模型上引发 SelectedItem

android - 如何使用具有相同 Fragment 的 4 个简单 ViewModel?

wpf - 是否保证在调用 OnStartup() 时所有 WPF 绑定(bind)都将起作用?

jQuery 验证不提交表单

jquery - Page_ClientValidate 未定义 (ASP.NET MVC)

php - 部分渲染的 div 内的 ajax 验证

javascript - 自定义表单验证表单

c# - 绑定(bind)命令的正确方法