我最终使用了以下方法。我将我的模型更改为使用LINQ到自跟踪实体(有关STE信息,请参见此文章
http://msdn.microsoft.com/en-us/library/vstudio/ff407090%28v=vs.100%29.aspx)。
LINQ到STE创建了一个OnPropertyChanged事件,实现了iNotifyPropertyChanged接口。
我只是为所需的匹配模型对象(linq实体生成代码)创建了一个公共部分类,并为OnPropertyChanged事件添加了事件处理程序。然后,我使用IDataErrorInfo接口进行验证并根据需要抛出错误。这使我能够在字段更改时验证它们,从而反映给用户。这还允许您执行可能需要重新查询数据库(例如查找用户名是否已被使用等)或抛出对话框的更高级别的验证逻辑。
此外,在模型中进行数据验证仍然允许我在执行直接“批量”操作(绕过UI)时进行验证。
我使用了HasErrors
和HasChanges
属性,并将它们用于创建一个布尔值,该值附加到继电器命令上,如果存在错误,则禁用crud命令按钮。
我将发布一些简单的代码来概述我刚才描述的内容,如果您需要更多细节,请评论。
这是模型类的Entity Framework扩展:
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命令按钮。
这真是一场艰苦的战斗,才弄明白这些。