【问题标题】:Data Validation with MVVM-Light WPF and Linq to Entity Framework使用 MVVM-Light WPF 和 Linq to Entity Framework 进行数据验证
【发布时间】:2013-01-19 07:20:15
【问题描述】:

当我搜索 wpf mvvm-light 数据验证时,我想我已经阅读了谷歌返回的每篇文章,但我不知道该走哪条路。我知道 josh smith、Karl Shifflett 和 MVVM LIGHT 自己的数据验证演示技术。我看到的是,大多数验证都需要我在我的视图模型中完全“重新抽象”我的模型。这意味着我必须在我的视图模型中为我想要验证的模型的每个属性创建一个属性(并且在某些情况下将所有这些转换为字符串值以进行绑定/验证)。当我想要做的只是根据需要标记大多数字段时,这似乎很多或冗余。

我正在为来自 SQL 服务器数据库的模型类使用 LINQ 到实体框架(具有自我跟踪功能)。因此,我更愿意将我的业务数据验证/规则保留在我的视图模型中。我编写了一个简单的服务接口来从模型中获取数据并将其传递给我的视图模型。

我能找到的大多数例子都可以追溯到 2008 年(即 josh smith)。这些技术是否仍然有效,或者是否有更多使用 .NET 4.5 等进行 mvvm 数据验证的最新最佳实践。

所以我问:

1) 你建议我使用什么方法 2) 什么方法在带有 MVVM-Light 环境的 LINQ to EF 中效果最好。 3)编辑:我想在用户输入数据时向他们提供反馈,而不仅仅是在他们提交表单时

谢谢

【问题讨论】:

    标签: wpf mvvm linq-to-entities mvvm-light


    【解决方案1】:

    我这样做的方式(不一定正确)是在 ViewModel 中进行验证(通常在其中进行 CRUD 操作),然后如果存在验证错误,则中止保存/添加任何数据并使用 Messenger.Default.Send 来将自定义消息类型发送到我的视图。然后我通过对话框或其他方式提醒用户。

    我过去曾尝试过 Binding ValidationRules,但发现迄今为止最可靠和最一致的方法是简单的if 语句。

    【讨论】:

    • 所以我假设您没有在用户在表单中输入数据时向他们提供反馈,而是在调用 crud 命令对象时进行验证。
    • 没错。如果你想提供实时反馈,我想你需要一个绑定验证规则,但我从来没有在这些方面取得太大成功。
    【解决方案2】:

    我最终最终使用了以下内容。我将模型更改为使用 LINQ 来自我跟踪实体(有关 STE http://msdn.microsoft.com/en-us/library/vstudio/ff407090%28v=vs.100%29.aspx 的信息,请参阅这篇文章)。

    LINQ to STE 创建一个实现 iNotifyPropertyChanged 接口的 OnPropertyChanged 事件。

    我刚刚为我想要的匹配模型对象(linq 实体生成的代码)创建了一个公共部分类,并为OnPropertyChanged 事件添加了一个事件处理程序。然后我使用IDataErrorInfo 接口来验证并根据需要抛出错误。这使我可以在字段更改时验证它们并反映给用户。这还允许您执行更高级的验证逻辑,可能需要重新查询数据库(即查找用户名是否已被使用等)或抛出一个对话框

    此外,如果我执行绕过 UI 的直接“批处理”操作,在模型中进行数据验证仍然可以进行验证。

    然后我使用 HasErrorsHasChanges 属性并使用它们创建一个附加到中继命令的布尔值,如果出现错误,则禁用 crud 命令按钮。

    我将发布一些简单的代码来概述我刚刚描述的内容,如果您需要更多详细信息,请发表评论。

    这里是模型类的实体框架扩展:

     Imports System.ComponentModel
    
    
    Partial Public Class client
    
        Implements IDataErrorInfo
    
    #Region "Properties / Declarations"
    
        'Collection / error description
        Private m_validationErrors As New Dictionary(Of String, String)
        Private _HasChanges As Boolean = False
    
        ''Marks object as dirty, requires saving
        Public Property HasChanges() As Boolean
            Get
                Return _HasChanges
            End Get
            Set(value As Boolean)
                If Not Equals(_HasChanges, value) Then
                    _HasChanges = value
                    OnPropertyChanged("HasChanges")
                End If
            End Set
        End Property
    
        'Extends the class with a property that determines
        'if the instance has validation errors
        Public ReadOnly Property HasErrors() As Boolean
            Get
                Return m_validationErrors.Count > 0
            End Get
        End Property
    
    #End Region
    
    #Region "Base Error Objects"
        'Returns an error message
        'In this case it is a general message, which is
        'returned if the list contains elements of errors
        Public ReadOnly Property [Error] As String Implements System.ComponentModel.IDataErrorInfo.Error
            Get
                If m_validationErrors.Count > 0 Then
                    Return "Client data is invalid"
                Else
                    Return Nothing
                End If
            End Get
        End Property
    
        Default Public ReadOnly Property Item(ByVal columnName As String) As String Implements System.ComponentModel.IDataErrorInfo.Item
            Get
                If m_validationErrors.ContainsKey(columnName) Then
                    Return m_validationErrors(columnName).ToString
                Else
                    Return Nothing
                End If
            End Get
        End Property
    
    #End Region
    
    #Region "Base Error Methods"
    
        'Adds an error to the collection, if not already present
        'with the same key
        Private Sub AddError(ByVal columnName As String, ByVal msg As String)
            If Not m_validationErrors.ContainsKey(columnName) Then
                m_validationErrors.Add(columnName, msg)
            End If
        End Sub
    
        'Removes an error from the collection, if present
        Private Sub RemoveError(ByVal columnName As String)
            If m_validationErrors.ContainsKey(columnName) Then
                m_validationErrors.Remove(columnName)
            End If
        End Sub
    
    #End Region
    
        Public Sub New()
    
            Me.HasChanges = False
        End Sub
    
    #Region "Data Validation Methods"
    
        ''handles event and calls function that does the actual validation so that it can be called explicitly for batch processes
        Private Sub ValidateProperty(ByVal sender As Object, ByVal e As PropertyChangedEventArgs) Handles Me.PropertyChanged
            If e.PropertyName = "HasChanges" Then
                Exit Sub
            End If
            IsPropertyValid(e.PropertyName)
            HasChanges = True
        End Sub
    
        Public Function IsPropertyValid(sProperty As String) As Boolean
            Select Case sProperty
                ''add validation by column name here
                Case "chrLast"
                    If Me.chrLast.Length < 4 Then
                        Me.AddError("chrLast", "The last name is too short")
                        Return True
                    Else
                        Me.RemoveError("chrLast")
                        Return False
                    End If
                Case Else
                    Return False
    
            End Select
    
        End Function
    
    #End Region
    
    End Class
    

    然后在视图模型中我包含以下代码来绑定命令并评估它是否可以执行。

     Public ReadOnly Property SaveCommand() As RelayCommand
            Get
                If _SaveCommand Is Nothing Then
                    _SaveCommand = New RelayCommand(AddressOf SaveExecute, AddressOf CanSaveExecute)
                End If
                Return _SaveCommand
            End Get
        End Property
    
        Private Function CanSaveExecute() As Boolean
            Try
                If Selection.HasErrors = False And Selection.HasChanges = True Then
                    Return True
                Else
                    Return False
                End If
            Catch ex As Exception
                Return False
            End Try
    
        End Function
    
        Private Sub SaveExecute()
            ''this is my LINQ to Self Tracking Entities DataContext
            FTC_Context.SaveChanges()
        End Sub
    

    以下是我绑定按钮的方式(在 WPF 中有自定义样式)

     <Button Content="" Height="40" Style="{DynamicResource ButtonAdd}" Command="{Binding SaveCommand}" Width="40" Cursor="Hand" ToolTip="Save Changes" Margin="0,0,10,10"/>
    

    因此,当没有验证错误且当前客户端记录“isDirty”时,保存按钮会自动启用,如果这两个条件中的任何一个条件失败,则会禁用。这样,我现在有了一种简单的方法来验证我想要的实体的任何类型的列/数据,并且我可以在用户在表单中输入数据时提供反馈,并且只有在我的所有“条件”都被启用后才启用 CRUD 命令按钮遇到了。

    这是一场需要弄清楚的战斗。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-31
      相关资源
      最近更新 更多