2

I have the following class where I have implemented IDataErrorInfo Interface but it doesn't work i.e it doesn't do the validation. The code seems perfect. I dont know why. I put a break point and It doesn't even enter into the IDataErrorInfo Members region.

Product class

[DataContract()]
public class Product : IDataErrorInfo
{
    [DataMember()]
    public string Name{get;set;}
    [DataMember()]
    public string Code{get;set;}

    #region IDataErrorInfo Members

    public string Error
    {
        get
        {
            return null;
        }
    }

    public string this[string property]
    {
        get
        {
            switch (property)
            {
                case "Name":
                    if (string.IsNullOrEmpty(Name))
                        return "Name is required";
                    break;
                case "Code":
                    if (string.IsNullOrEmpty(Code))
                        return "Code is required";
                    break;
                default:
                    break;
            }
            return null;
        }
    }

    #endregion

    public Product(string name, string code)
    {
        Name = name;
        Code = code;
    }
 }

XAML for Binding a textbox

<TextBox Grid.Column="1" 
                         HorizontalAlignment="Left" 
                         Height="23" 
                         Margin="24,9,0,0" 
                         TextWrapping="Wrap" 
                         VerticalAlignment="Top" 
                         Width="148" x:Name="txtName" 
                         Text="{Binding Name,Mode=TwoWay,ValidatesOnDataErrors=True}" 
                         MaxLength="50"/>
Huma Ali
  • 1,759
  • 7
  • 40
  • 66

1 Answers1

3

You need to make your object observable using INotifyPropertyChanged along with the IDataErrorInfo in order for the the binding to know that properties have changed and to check if there were any errors when ValidatesOnDataErrors=True

public class Product : IDataErrorInfo, INotifyPropertyChanged {
    string _name;
    [DataMember()]
    public string Name{
        get { return _name; }
        set {
            _name = value;
            NotifyPropertyChanged("Name");
        }
    }

    //...Other code removed for brevity

    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged(string propertyName) {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

You could even move the property changed functionality out into a base class for reuse like so

public abstract class PropertyChangedBase: INotifyPropertyChanged {

    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged(string propertyName) {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

and use it like

public class Product : PropertyChangedBase, IDataErrorInfo {
    //Code removed for brevity
}
Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • Thanks I got it working. I have another question apart from this, I created a class in my `ASP.NET` `.Web` project and I'm trying to create an object of it in the `MainPage.xaml.cs` class but seems like its not possible? Can you guide? – Huma Ali Feb 01 '16 at 06:12
  • You created the initial object/class for silverlight *only*, which is not accessible to the web project. if you are trying to share models between different project types then I suggest you create a shared PCL `(Portable Class Library)` so that you can reference it from asp.net.web project. – Nkosi Feb 01 '16 at 09:52
  • How about a `Silverlight Class Library`? – Huma Ali Feb 01 '16 at 09:55
  • Silverlight class library can only be referenced from other silverlight libraries. Lookup up Portable class library and then when you have an understanding of it, create one that can be referenced from both silverlight and the web project. – Nkosi Feb 01 '16 at 10:01
  • Ok let me check out the PCL. Thanks – Huma Ali Feb 01 '16 at 10:10
  • One more thing I'd like to ask, ho can I know the state of `validations`? Like I have a `Button` that I want to `Disable` in case of Validation failures and `Enable` on Success. How can I do this from Code behind? – Huma Ali Feb 01 '16 at 11:21
  • 1
    A manual dirty fix for what you want is to create a `bool` property like `IsValid` for example, that wraps the errors of your model. If no errors return true otherwise return false. You can then Bind that property to the `IsEnabled` of your button. – Nkosi Feb 01 '16 at 11:29
  • I had this thing in mind but I was looking for a more clean and better approach for this. Thanks anyway :) – Huma Ali Feb 01 '16 at 11:32
  • 1
    The cleaner approach would be to use the `Commanding` pattern using `ICommand` and bind the button to the command property. look it up. – Nkosi Feb 01 '16 at 11:33