在M-V-VM中使用IDataErrorInfo

12
如果我的领域对象实现了IDataErrorInfo接口,并且我正在使用M-V-VM,那么我该如何将错误传递到ViewModel并显示在View中?如果我直接绑定到模型,我会在绑定上设置"ValidateOnExceptons"和"ValidateOnErrors"属性为真。但是我的ViewModel没有实现IDataErrorInfo接口,只有我的模型实现了。我该怎么办? 澄清 我正在处理一个现有的代码库,其中领域对象实现了IDataErrorInfo接口。我不能在我的视图模型中实现IDataErrorInfo接口。
4个回答

18

您可以在VM中另外实现IDataErrorInfo,并将调用路由到VM以针对相应的域对象。 我认为这是唯一的方式,而不必直接向视图公开域对象。


你正在使用什么来将调用路由到绑定实体中的VM实现? - TheCodeKing
我没有实现它,但我认为你必须手动完成。 - MarioH
嗯,听起来行不通,我正在寻找一种告诉WPF在视图模型上查找IDataErrorInfo的方法。 - TheCodeKing

7
如果您正在使用M-V-VM,ViewModel应该定义IDataErrorInfo接口,而不是模型。
可以说,IDataErrorInfo接口仅适用于视图,不属于模型,但这是一种风格问题。
让ViewModel实现IDataErrorInfo接口并从模型传播错误将是最简单的答案。

和上面的问题一样,你如何将实体中的错误传递到视图模型?你已经成功做到了吗? - TheCodeKing
3
这个答案与微软最佳实践(http://msdn.microsoft.com/en-us/library/gg405484(v=PandP.40).aspx)相矛盾:通常,模型实现了使其易于绑定到视图的设施。这通常意味着它支持通过INotifyPropertyChanged和INotifyCollectionChanged接口进行属性和集合更改通知。该模型还可以通过IDataErrorInfo(或INotifyDataErrorInfo)接口支持数据验证和错误报告。这些接口允许WPF和Silverlight数据绑定在值更改时被通知,以便更新UI。 - Pat
7
@Pat,我不确定我同意你的观点。模型不应该受到UI方面的污染。只是为了让UI满意而在模型中实现一些接口并不合适,这就是ViewModel的作用。然而,这全部取决于模型的复杂性、项目的大小和类型等因素。我不认为有一个真正的答案。但我会尽量保持模型不受业务逻辑之外的任何问题的干扰。 - gcores
@gcores 这就是我感觉的方式,但我只是指出微软的回答似乎是这样(尽管不是一个充分论证的答案)。 - Pat

3
这个主题有一篇很好的MSDN Magazine文章,讲述了使用MVVM设计模式的WPF应用程序:http://msdn.microsoft.com/en-us/magazine/dd419663.aspx 根据这篇文章中的数据模型和存储库部分(http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090102),您将找到一个简单的实现。客户是实体类,ViewModel从实体获取错误指示器。
您可以使用ValidationsRule来检查数据的有效性:
<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>

这是一个验证器样式的示例:
<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>



0

WPF应用程序框架(WAF)BookLibrary示例应用程序可能会对您感兴趣。它在域对象上实现了IDataErrorInfo接口,并使用了M-V-VM模式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接