katie77
katie77

Reputation: 1811

Data Validation in MVVM light

What is the best way to do data validation. Is it a good practice to do validation in view models or should the validation be done in models? and also, what is the best way to implement numeric(decimal) text-box in WPF with MVVM. I am using MVVM Light toolkit.

Upvotes: 5

Views: 8657

Answers (3)

blindmeis
blindmeis

Reputation: 22445

If you use IDataErrorInfo for Viewmodel validation - DO NOT FORGET the following:

if your viewmodel has properties other then typeof string and the input in your view can not be converted to the property type - then your input never reach the viewmodel and so the validation - and the user in front of the view is just thinking: "wtf why i dont see any validation error!"

Upvotes: 0

Nivid Dholakia
Nivid Dholakia

Reputation: 5442

Implement IDataError Info on the class and that will implement two properties Error and this[string columnName] you can implement the second property with your binding errors that you want

public class MainViewModel:ViewModelBase,IDataErrorInfo  
{

public string Error
   {
   }
 public string this[string columnName]

 {
  get
      {
         string msg=nulll;
         switch(columnName)
            {
              case "MyProperty": //that will be your binding property
               //choose your validation logic
               if(MyProperty==0||MyProperty==null)
                 msg="My Property is required";
                break;
             }
         return msg;
        }
}

Also set ValidateOnError=true on the fields

Upvotes: 1

Daniel Hilgarth
Daniel Hilgarth

Reputation: 174329

To be able to provide meaningful messages to the user, it is best to make the properties of your ViewModel that should be bound to a TextBox of type string and implement IDataErrorInfo on your ViewModel.

In my projects, I am using it like this. I created an interface IValidateable (please forgive the name...) which implements IDataErrorInfo. My ViewModel implements this interface:

public interface IValidateable : IDataErrorInfo
{
    ObservableCollection<Tuple<string, ValidationError>> InvalidProperties
    { get; }
    bool IsValid { get; }
}

All my text boxes use the following style:

<Style TargetType="{x:Type TextBox}">
    <Style.Triggers>
      <Trigger Property="Validation.HasError"
               Value="true">
        <Setter Property="ToolTip"
                Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}" />
      </Trigger>
    </Style.Triggers>
    <Setter Property="Validation.ErrorTemplate">
      <Setter.Value>
        <ControlTemplate>
          <Grid>
            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="90*" />
              <ColumnDefinition Width="20" />
            </Grid.ColumnDefinitions>
            <Border BorderBrush="Red"
                    BorderThickness="1"
                    CornerRadius="2.75"
                    Grid.Column="0">
              <AdornedElementPlaceholder Grid.Column="0" />
            </Border>
            <TextBlock Foreground="Red"
                       Grid.Column="1"
                       Margin="0"
                       FontSize="12"
                       VerticalAlignment="Center"
                       HorizontalAlignment="Left">
              *
            </TextBlock>
          </Grid>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>

This will show a tool tip if the value entered doesn't conform to my rules.

Furthermore, I created a small validation engine which allows to assign rules to the properties of the view model and a base class that automatically validates the property value when a new value is set.
The interface members of IValidateable are used to display a meaningful error message to the user when he tries to save an invalid object.

Upvotes: 6

Related Questions