12

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.

Micah
  • 111,873
  • 86
  • 233
  • 325

4 Answers4

18

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.

MarioH
  • 1,165
  • 2
  • 9
  • 15
7

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.

gcores
  • 12,376
  • 2
  • 49
  • 45
  • Same question as above, how do you propagate the errors from the entity to the veiwmodel? Have you managed to do this? – TheCodeKing Sep 17 '10 at 20:16
  • 3
    This answer contradicts best practices from MS (http://msdn.microsoft.com/en-us/library/gg405484(v=PandP.40).aspx): Typically, the model implements the facilities that make it easy to bind to the view. This usually means it supports property and collection changed notification through the INotifyPropertyChanged and INotifyCollectionChanged interfaces. The model may also support data validation and error reporting through the IDataErrorInfo (or INotifyDataErrorInfo) interfaces. These interfaces allow WPF and Silverlight data binding to be notified when values change so that the UI can be update – Pat Dec 01 '10 at 16:06
  • 7
    @Pat I'm not sure I agree with that. The model shouldn't be polluted with UI concerns. Implementing a couple of interfaces in the model just to make the UI happy doesn't feel right, that's what the ViewModel is for. Then again, it all depends on the complexity of the model, the size and type of the project, etc. I don't think there's a true answer. But I would try to keep the model clean of any concerns outside business logic. – gcores Dec 01 '10 at 22:06
  • @gcores That's sort of how I feel, but I was just pointing out what the Microsoft answer seems to be (albeit not a well-justified answer). – Pat Dec 01 '10 at 23:35
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>


artur02
  • 4,469
  • 1
  • 22
  • 15
0

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.

jbe
  • 6,976
  • 1
  • 43
  • 34