【问题标题】:Data Validation in MVVM lightMVVM light 中的数据验证
【发布时间】:2011-09-27 14:09:47
【问题描述】:

进行数据验证的最佳方法是什么。在视图模型中进行验证是一种好习惯,还是应该在模型中进行验证?还有,在 WPF 中使用 MVVM 实现数字(十进制)文本框的最佳方法是什么。我正在使用 MVVM Light 工具包。

【问题讨论】:

  • 我更倾向于在视图模型而不是模型中进行验证,因为在我的模型中,模型对象正在被服务公开。我可以控制服务。但我认为在视图模型中这样做会更好,因为验证取决于视图。在一个视图中,为属性赋值可能是必需的,但在另一个视图中是可选的。

标签: wpf mvvm mvvm-light


【解决方案1】:

为了能够向用户提供有意义的消息,最好将 ViewModel 的属性绑定到字符串类型的 TextBox 并在 ViewModel 上实现 IDataErrorInfo

在我的项目中,我是这样使用它的。我创建了一个实现 IDataErrorInfo 的接口IValidateable(请原谅名称...)。我的 ViewModel 实现了这个接口:

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

我所有的文本框都使用以下样式:

<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>

如果输入的值不符合我的规则,这将显示一个工具提示。

此外,我创建了一个小型验证引擎,它允许将规则分配给视图模型的属性和一个在设置新值时自动验证属性值的基类。
IValidateable 的接口成员用于在用户尝试保存无效对象时向用户显示有意义的错误消息。

【讨论】:

    【解决方案2】:

    在类上实现 IDataError 信息,这将实现两个属性 Error 和 this[string columnName] 你可以用你想要的绑定错误实现第二个属性

    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;
            }
    }
    

    还要在字段上设置 ValidateOnError=true

    【讨论】:

    • 在我的例子中,要在模型中执行此操作,模型对象正在被服务公开。我可以控制服务。但我认为在视图模型中这样做会更好,因为验证取决于视图。在一个视图中,为属性赋值可能是必需的,但在另一个视图中是可选的。
    • 你也可以在模型中做到这一点!仅作为示例您有一个绑定到本地视图模型的 MyProperty 的文本框。但是 If Model Then Objectof the Model.Property。问题是 IDataErrorInfo 必须在那个 HelperClass 上实现
    【解决方案3】:

    如果您使用 IDataErrorInfo 进行 Viewmodel 验证 - 请不要忘记以下内容:

    如果您的视图模型具有 typeof 字符串以外的属性,并且您的视图中的输入无法转换为属性类型 - 那么您的输入永远不会到达视图模型,因此验证 - 视图前面的用户只是在思考:“为什么我没有看到任何验证错误!”

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多