Silverlight 4, Validation error state doesn't get reflected in my own custom UserControl

霸气de小男生 提交于 2019-12-13 18:23:17

问题


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

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.

This is my UserControl code:

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

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}" />

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

回答1:


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


来源:https://stackoverflow.com/questions/7349627/silverlight-4-validation-error-state-doesnt-get-reflected-in-my-own-custom-use

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!