Saturday, January 24, 2015

Using INotifyDataErrorInfo & Data Annotations [Required] Attribute in WPF on Objects

INotifyDataErrorInfo in combination with Data Annotations works great for error validation in WPF when using .NET 4.5.  A typically example of data annotations shows them being used on properties with primitive types such as integer or string.  When binding in WPF, one would bind a control such as a text box directly to the primitive property.  Error validation would occur on that binding.

     public string Name  
       get { return _name; }  
       set { SetProperty(ref _name, value); }  

      <TextBlock Text="{Binding Name}"/>  

Recently, I was working with some code that had a [Required] attribute on an object.  In the view-model the binding was to a nested property on that object. 

     public MaterialModel LinerMaterial  
       get { return _linerMaterial; }  
       set { SetProperty(ref _linerMaterial, value); }  

    <TextBlock Text="{Binding LinerMaterial.Name}"/>  

Validation was not working!  Validation attributes only work directly against the object to which they are applied.  I could have created a separate primitive property "MaterialName" and set that when a material was selected on the view model.  However, I decided to go with a slightly different solution.  I wrapped my text block with a stack panel, setting the data context of the stack panel to the MaterialModel object.

 <TextBlock HorizontalAlignment="Left" Text="Liner Material:"/>  
 <StackPanel DataContext="{Binding LinerMaterial}">  
      <TextBlock Text="{Binding .Name}"/>  

  Doing this causes validation to be raised on the stack panel, instead of the TextBlock.  
Error validation of the object showing on the stack panel
This could be considered a bit of a hack, but on the view model I was working on, it saved me from having to add three extra properties for primitives, and additional logic.  Also, I feel it conveys the intent better.  The view model doesn't require a material name, it requires a material.

No comments:

Post a Comment