Getting most basic MetaDataType to work

158 Views Asked by At

In addition to my original post I guess I need to mention that I am using Prism 6.3. Apparently, the compiler doesn't like stuff added to the metadata class that's not in the original partial. Not sure how to resolve this. Thanks again ... Ed

Ok, I give, UNCLE!

I am trying to add data annotations to my wpf entity framework app. I've tried 6 ways to Sunday with no luck. I put together what is what I consider the most simple example possible and followed all the instructions ... nothing works. Here goes. I have a class that is generated by EF (db first).

namespace junk.DataModels
{
    public partial class MyClass
    {
        public string SomeText { get; set; }
    }
}

I have another file with the following partial class:

namespace junk.DataModels
{
    [MetadataType(typeof(MyClassMetaData))]
    public partial class MyClass
    {
    }

    public partial class MyClassMetaData
    {
      private string _someText;
      [Required(ErrorMessage = "Required")]
      public string SomeText 
      {
          get { return _someText; }
          set { SetProperty(ref _someText, value); }
      }
    }
}

In my ViewModel I define:

private MyClass _mc;
public MyClass MC
{
    get { return _mc; }
    set
    {
        SetProperty(ref _mc, value);
    }
}

And in the constructor:

MC = new MC();
MC.SomeText = "Hello World.";

Lastly, in my xaml:

I have a single bound control:

<TextBox x:Name="txt" Text="{Binding MC.SomeText, 
        ValidatesOnDataErrors=True, 
        ValidatesOnExceptions=True,
        ValidatesOnNotifyDataErrors=True,
        UpdateSourceTrigger=PropertyChanged }"
 />

According to everything I've read, if I run this and clear the textbox, I should get a validation error. I have tried all combinations of "ValidatesOn" it doesn't seem to make a difference. Can someone take pity on me and share the secret sauce? I must be missing something simple. If I bind to the metadataclass it works but that is kinda defeating the purpose.

Any help would be great!

1

There are 1 best solutions below

0
On

Try adding the following static constructor to your buddy class "MyClass". It will register the metadata against your EF class so the Validator can find the Data Annotations:

static MyClass()
{
    // Register the metadata against our EF data object. 
    // This will ensure the Validator find the annotations
    TypeDescriptor.AddProviderTransparent(
        new AssociatedMetadataTypeTypeDescriptionProvider(
            typeof(MyClass), 
            typeof(MyClassMetaData)), 
            typeof(MyClass)
    );
}

You could also try running a unit test to confirm whether the Validator has used your annotation, before adding the complexity of the GUI:

[TestMethod]
public void TestAnnotations()
{
    MyClass c = new MyClass();

    // Manually validate the MyClass object
    List<ValidationResult> validationResults = new List<ValidationResult>();
    ValidationContext context = new ValidationContext(c, serviceProvider: null, items: null);
    bool isValid = Validator.TryValidateObject(c, context, validationResults, validateAllProperties: true);

    Assert.IsFalse(isValid, "Validation should fail because we didn't set SomeText");

}