最終的には以下を使用することになりました。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をバイパスする直接の「バッチ」操作を実行した場合でも検証を行うことができます。
次に、HasErrors
andHasChanges
プロパティを使用し、それらを使用して、リレーコマンドに付加されるブール値を作成し、エラーが存在する場合はcrudコマンドボタンを無効にしました。
今説明した内容の概要を説明する簡単なコードを投稿します。詳細が必要な場合はコメントしてください。
モデルクラスのEntityFramework拡張機能は次のとおりです。
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」の場合、保存ボタンは自動的に有効になり、これら2つの条件のいずれかが失敗した場合は無効になります。このようにして、エンティティに必要な任意のタイプの列/データを検証する簡単な方法があり、フォームにデータを入力するときにユーザーフィードバックを提供し、すべての「条件」が完了した後でのみCRUDコマンドボタンを有効にすることができます。会った。
これは理解するのにかなりの戦いでした。