I am attempting to implement some simple validation on a textbox in MVVM
public string Property
{
get
{
if (App.PropertyStorageContainer != null)
{
return App.PropertyStorageContainer.Property;
}
else
{
return null;
}
}
set
{
App.PropertyStorageContainer.Property = value;
RaisePropertyChanged("Property");
}
}
Then in my PropertyStorageContainer class I have
private string _property;
public string Property
{
get
{
return App.PropertyStorageContainer.Property;
}
set
{
if(value meets some condition)
{
_property = value;
}
else
{
_property = someothervalue;
}
}
}
.
<TextBox Width="50" TextAlignment="Center" Text="{Binding Property, Mode=TwoWay, NotifyOnValidationError=True}" MaxLength="3"></TextBox>
The point of this is to validate what goes in the box. Now if I set this value directly from my code then everything works as I would expect. It attempts to SET the value, then calls RaiseProperyChanged, then GET the value (which because of the validation may not be the same value that was entered originally). The final value retrieved does show up on the view, so I know TwoWay binding is working.
The problem I have is when the input for SET comes from the bound XAML property / directy from user. In this case the SET method is called, the validation performed, but the GET never happens. This results in the unvalidated value remaining in the textbox on screen.
My first question would be is this a bug or expected behavior? I can see how maybe they tried to save performance by removing that last GET when the input came straight from the user since there should be nothing new to GET. But if not then maybe the way I have it all setup is interfering with the GET being called.
Second question is of course any suggestions for getting around this one. I’ve read a few suggestions for other methods of doing validation, but my program is already live on PROD and most of the changes being suggested involve a lot of rework for me so I am hoping to find a way to make it call GET any time the property is SET.
I have made a couple of assumptions since I am not sure I understand you code completely but I think you could consider possibly implementing a custom validation rule. First off, since your custom ValidationRule will take care of the validation you could get the logic out of your model class’s property definition and “dumb down” your poco:
It seems you desire your view model to act as a basic wrapper around your model class. Again, I will assume this is valid based on the description of your scenario:
Now create a new class that extends System.Windows.Controls.ValidationRule and override the abstract Validate method in order implement your validation logic. For the example, I created a rule that just checks if the string is null or empty (assuming that would be an invalid scenario):
Now for the XAML… Here is an example of a TextBox that adds the validation rule to its binding validation rules (can be multiple rules).
Then define the following resources (referenced above) somewhere (e.g., Window.Resources). First a ControlTemplate to define how the TextBox should look when in invalid state:
Additionally you could define a style trigger to display the error message. Here I just bind it to the ToolTip property of the TextBox: