0
votes

FYI: Using .NET 4.5 and Silverlight 5 in VS 2012 Ultimate.

My [Required] and Length data annotations do not want to buble up into my Silverlight form and validate. I have a fairly straight forward class exposed via a DDS. Example:

public class FooCard : INotifyPropertyChanged
{
    [Key]
    [Required]
    [IntegerValidator(MinValue = 0, MaxValue = 32768)]
    public short FooID { get; set; }

    [Required]
    [StringLength(15)]
    public string FooName { get; set; }

My XMAL looks like this:

<TextBlock Height="25" Text="FooID:" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right"
                                Margin="0,0,2,0">
</TextBlock>
<TextBox Name="TextBox_FooID" Text="{Binding Path=FooID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" Grid.Column="1" TextChanged="TextBox_TextChanged">
</TextBox>
<TextBlock Height="25" Text="Foo Name:" Grid.Row="2" Grid.Column="0" HorizontalAlignment="Right"
                                    Margin="0,0,2,0">
</TextBlock>
<TextBox Name="TextBox_FooName" Text="{Binding Path=FooName, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged}" Grid.Row="2" Grid.Column="1"
                             TextChanged="TextBox_TextChanged"
                             LostFocus="TextBox_FooName_LostFocus">

DDS is set to auto load false and the query parameter is bound to FooID text box. Initally, when someone loads the form I set the data context to my DDS and I do not execute a load opperation on the DDS in this case because the user selects they are creating a "New Foo" record. So, the DataView.CurrentItem is null at this point. This is what's happening:

If a user starts to type something into a bound field with annotations like FooID, it immediately runs any annotation validators on that field only. A red box shows up saying the min length. But, nothing validates other bound properties like on FooName in my example. I can actually submit the changes with a empty fooName and a validation errors exception is thrown. Of course, I bind my save changes button to the HasValidationErrors property of my DDS so this won't happen to the user. But, the user in confused as to why the save changes button is disabled and there's no red box requiring them to enter something into fooName. I can of course just create a label or put * next to the box indicating it's required.

But, I can get around this by loading FooName = " "; FooName = string.empty; in codebehind on OnNavigatedTo. Once it loads the space and then is set to an empty string again, it shows up with a red box. It's almost like Silverlight is requiring each property to be initialized first or something. This seems like a total hack and I hate to require that the 50+ textboxes on my form all get set to some bogus initial value and back again. ie. it's not a resolution but a troubleshooting step.

What is going on here? I'm still a pretty new developer who is more of a life long DBA (only a year now in developing SL solutions) and I just started using validators in my classes instead of poor man's validation in codebehind and button click events etc. But, couldn't find a lot of information in google / bing for this sort of issue occuring. Any insight is appreciated. I'm sure I'm probably going about something the wrong way.

1

1 Answers

1
votes

The problem is that Validation for DataAnnotations only fires in the Property Setter, and then the Binding engine will only pick it up if the Setter is called via the Binding. If you want to show validation errors for all properties, you must implement INotifyDataErrorInfo.

With this interface implemented, you can set Validation Errors from code whenever you want. If it helps, you can also use the Validator class to get validation errors for each property eg:

Validator.ValidateProperty(valueToValidate, 
    new ValidationContext(this, null, null) { MemberName = "MyProperty" } );