Silverlight 4,验证错误状态未反映在我自己的自定义UserControl中

问题描述:

验证错误状态未反映在我的UserControl中。我正在遵循类似的 *问题来解决。我没有选择使用MVVM方法。它正在使用带有Entity Framework的WCF RIA服务。

Validation error state doesn't get reflected in my UserControl. I was following this similar * question to solve it. I am not using an MVVM approach by choice. It's using WCF RIA Services with Entity Framework.

但是它似乎没有帮助我,我想念什么,或者为什么我的情况与众不同?
注意:如果我在主页上放置一个TextBox(不在UserControl内),它将显示验证错误。

But it didn't seem to help me, what am I missing, or why is my scenario different? Note: If I put a TextBox (not inside the UserControl) in my main page, it shows validation error.

这是我的UserControl代码:

<UserControl x:Class="TestApp.MyUserControl"     
         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="25" d:DesignWidth="120">
    <Grid x:Name="LayoutRoot" Background="White">
        <TextBox x:Name="TextBox" />
    </Grid>
</UserControl> 

这是UserControl的代码:

and this is the code behind of the UserControl:

public partial class MyUserControl : UserControl, INotifyDataErrorInfo
{
    public MyUserControl()
    {
        InitializeComponent();

        this.TextBox.BindingValidationError += MyUserControl_BindingValidationError;
        Loaded += MyUserControl_Loaded;
        this.TextBox.Unloaded += MyUserControl_Unloaded;
    }

    private void MyUserControl_Loaded(object sender, RoutedEventArgs e)
    {
        this.TextBox.SetBinding(TextBox.TextProperty,
            new Binding()
            {
                Source = this,
                Path = new PropertyPath("Value"),
                Mode = BindingMode.TwoWay,
                NotifyOnValidationError = false,
                ValidatesOnExceptions = true,
                ValidatesOnDataErrors = true,
                ValidatesOnNotifyDataErrors = true
            });
    }

    private void MyUserControl_Unloaded(object sender, RoutedEventArgs e)
    {
        this.TextBox.ClearValue(TextBox.TextProperty);
    }

    public static DependencyProperty ValueProperty =
        DependencyProperty.Register("Value",
        typeof(string), typeof(MyUserControl),
        new PropertyMetadata(null));

    public static void ValuePropertyChangedCallback(DependencyObject dependencyObject, 
        DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
    {
        ((MyUserControl)dependencyObject).NotifyErrorsChanged("Value");
    }

    public string Value
    {
        get { return ((string)base.GetValue(ValueProperty)).Trim(); }
        set { base.SetValue(ValueProperty, string.IsNullOrEmpty(value) ? " " : value.Trim()); }
    }

    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

    public IEnumerable GetErrors(string propertyName)
    {
        IEnumerable returnValue = null;
        var errorMessage = "";

        if (propertyName == "Value")
        {

            if (Validation.GetErrors(this).Count == 0)
            {
                errorMessage = "";
            }
            else
            {
                errorMessage = Validation.GetErrors(this).First().ErrorContent.ToString();
            }

            if (String.IsNullOrEmpty(errorMessage))
            {
                returnValue = null;
            }
            else
            {
                returnValue = new List<String> { errorMessage };
            }
        }

        return returnValue;
    }

    public bool HasErrors
    {
        get { return Validation.GetErrors(this).Any(); }
    }

    private void MyUserControl_BindingValidationError(object sender, System.Windows.Controls.ValidationErrorEventArgs e)
    {
        this.NotifyErrorsChanged("Value");
    }

    public void NotifyErrorsChanged(string propertyName)
    {
        if (ErrorsChanged != null)
        {
            ErrorsChanged(this, new System.ComponentModel.DataErrorsChangedEventArgs(propertyName));
        }
    }
}

我正在这样使用在我的主页上:

I am using it like this in my main page:

<my:MyUserControl x:Name="UC"  
    Value="{Binding Path=Days, Mode=TwoWay,
            NotifyOnValidationError=True,
            ValidatesOnNotifyDataErrors=True}" />

我也在System.ComponentModel.DataAnnotations中使用验证属性,这就是 RIAService.metadata.cs类:

I am also using validation attributes in System.ComponentModel.DataAnnotations, this is how it looks in RIAService.metadata.cs class:

internal sealed class tblRiskRegisterMetadata
{
    //Metadata classes are not meant to be instantiated.
    private tblRiskRegisterMetadata()
    {  }

    [Range(0, 1000, ErrorMessage = "Days should be 0-100")]
    public int Days{ get; set; }
}


new PropertyMetadata(null) -> new PropertyMetadata(null, **ValuePropertyChangedCallback**)