Using IDataErrorInfo in M-V-VM

2020-02-10 18:50发布

问题:

If my domain objects implement IDataErrorInfo, and I am using M-V-VM, how do I propagate errors through the ViewModel into the View? If i was binding directly to the model, I would set the "ValidateOnExceptons" and "ValidateOnErrors" properties to true on my binding. But my ViewModel doesn't implement IDataErrorInfo. Only my model. What do I do?

Clarification I am dealing with an existing codebase that implements IDataErrorInfo in the domain objects. I can't just implement IDataErrorInfo in the my view model.

回答1:

You can implement IDataErrorInfo additionally in your VM and route the calls to the VM to your corresponding domain objects. I think this is the only way without exposing domain objects directly to the view.



回答2:

if you are using M-V-VM, the ViewModel should define the IDataErrorInfo interface, not the model.

You could say that the IDataErrorInfo interface is just for the view and it doesn't belong in the model, but that's a question of style.

Having the ViewModel implement the IDataErrorInfo interface and propagate the errors from the model would be the simplest answer.



回答3:

There is a good MSDN Magazine article on this topic, WPF Apps With The Model-View-ViewModel Design Pattern: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

According to this article, in The Data Model and Repository section (http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090102) you will find a simple implementation. The Customer is the entity class and the ViewModel gets the error indicators from the entity.

You can use ValidationsRule to check data validity:

<TextBox x:Name="title" VerticalAlignment="Top" TextWrapping="Wrap" Grid.Column="1" MinWidth="20">
  <TextBox.Text>
    <Binding Path="Title" UpdateSourceTrigger="LostFocus">
      <Binding.ValidationRules>
        <Validators:StringRangeValidationRule MinimumLength="1" MaximumLength="30" 
                                            ErrorMessage="Address is required and must be less than 30 letters." />
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>

This is an example of validator styling:

<Application.Resources>
  <Style TargetType="{x:Type TextBox}">
  <Setter Property="Validation.ErrorTemplate">
    <Setter.Value>
      <ControlTemplate>
        <DockPanel LastChildFill="True">
          <Image Source="/Images/error.png" Width="25" Height="25" ToolTip="{Binding ElementName=MyAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" />
          <TextBlock DockPanel.Dock="Right"
              Foreground="Orange"
              Margin="5" 
              FontSize="12pt"
              Text="{Binding ElementName=MyAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
          </TextBlock>

          <Border BorderBrush="Red" BorderThickness="3">
          <AdornedElementPlaceholder Name="MyAdorner" />
        </Border>
      </DockPanel>
    </ControlTemplate>
  </Setter.Value>
</Setter>
<Style.Triggers>
  <Trigger Property="Validation.HasError" Value="true">
    <Setter Property="ToolTip"
        Value="{Binding RelativeSource={RelativeSource Self}, 
        Path=(Validation.Errors)[0].ErrorContent}"/>
  </Trigger>
</Style.Triggers>




回答4:

The BookLibrary sample application of the WPF Application Framework (WAF) might be interesting for you. It implements the IDataErrorInfo interface as well on the domain objects and it uses the M-V-VM pattern.