まずは、データーフローから考えてみると
値の変更→データチェック→通知
OK => INotifyPropertyChange
NG => INotifyDataErrorInfo
という流れで実装する場合、
set {
if (validation(value)) {
//INotifyPropertyChange
}else{
//INotifyDataErrInfo
}
}
この辺りは共通処理になるからここをModelBaseクラスという形で実装しておき、
あとはSetProperty関数を用いて上記処理を処理させようというアプローチである。
過去にもModelがらみの記事に書いた
MongoDBと接続、もしくはJSonファイルに出力する方法にも使えるようにしておいた。
実装方法はModelBaseクラス内でNotify関連を実装してそれを任意のModelクラスに継承するやり方。
Imports System.ComponentModel
Imports MongoDB.Driver
Imports MongoDB.Driver.Builders
Imports MongoDB.Driver.Linq
Imports MongoDB.Bson
Imports MongoDB.Bson.Serialization.Attributes
'http://blog.micic.ch/net/easy-mvvm-example-with-inotifypropertychanged-and-inotifydataerrorinfo
Public Class ModelBase : Implements INotifyPropertyChanged, INotifyDataErrorInfo
#Region "data error"
Private _errors As New Dictionary(Of String, List(Of String))
Public Event ErrorsChanged(sender As Object, e As DataErrorsChangedEventArgs) Implements INotifyDataErrorInfo.ErrorsChanged
Public Function GetErrors(propertyName As String) As IEnumerable Implements INotifyDataErrorInfo.GetErrors
If _errors.ContainsKey(propertyName) Then
Return _errors(propertyName)
End If
Return Nothing
End Function
Public ReadOnly Property HasErrors As Boolean Implements INotifyDataErrorInfo.HasErrors
Get
Return 0 < _errors.Count
End Get
End Property
Public ReadOnly Property IsValid As Boolean
Get
Return Not HasErrors
End Get
End Property
Private Sub AddError(propertyName As String, errmsg As String)
If Not _errors.ContainsKey(propertyName) Then
_errors(propertyName) = New List(Of String)
End If
If Not _errors(propertyName).Contains(errmsg) Then
_errors(propertyName).Add(errmsg)
RaiseEvent ErrorsChanged(Me, New DataErrorsChangedEventArgs(propertyName))
End If
End Sub
Private Sub RemoveError(propertyName As String)
If _errors.ContainsKey(propertyName) Then
_errors.Remove(propertyName)
RaiseEvent ErrorsChanged(Me, New DataErrorsChangedEventArgs(propertyName))
End If
End Sub
#End Region
#Region "Property changed"
Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
#End Region
#Region "Set Property"
Private _lock As New Object()
Protected Delegate Function DlgCheckValidation() As String
Protected Sub SetProperty(Of T)(propertyName As String, ByRef field As T, value As T, func As DlgCheckValidation)
If Not EqualityComparer(Of T).Default.Equals(field, value) Then
SyncLock _lock
Dim errmsg = ""
If Not IsNothing(func) Then
errmsg = func()
End If
If "" = errmsg Then
field = value
RemoveError(propertyName)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
Else
AddError(propertyName, errmsg)
End If
End SyncLock
End If
End Sub
#End Region
End Class
<BsonIgnoreExtraElements>
Public Class AddressModel : Inherits ModelBase
<BsonId>
<DisplayName("ID")>
Public Property _id As BsonObjectId
Private _name As String
Private _birthday As Date
Private _emailAddress As List(Of EMailModel)
<DisplayName("名前")>
Public Property name As String
Get
Return _name
End Get
Set(value As String)
SetProperty("name", _name, value,
Function() As String
If "abc" = value Then
Return "abc not allowed"
End If
Return ""
End Function)
End Set
End Property
Public Property Birthday As Date
Get
Return _birthday
End Get
Set(value As Date)
SetProperty("Birthday", _birthday, value, Nothing)
End Set
End Property
Public Property EMailAddress As List(Of EMailModel)
Get
Return _emailAddress
End Get
Set(value As List(Of EMailModel))
SetProperty("EMailAddress", _emailAddress, value, Nothing)
End Set
End Property
End Class
<BsonIgnoreExtraElements>
Public Class EMailModel : Inherits ModelBase
Private _DisplayName As String
Private _MailAddress As String
Public Property DisplayName As String
Get
Return _DisplayName
End Get
Set(value As String)
SetProperty("DisplayName", _DisplayName, value, Nothing)
End Set
End Property
Public Property MailAddress As String
Get
Return _MailAddress
End Get
Set(value As String)
SetProperty("MailAddress", _MailAddress, value, Nothing)
End Set
End Property
End Class
参照サイト:
http://ivis-mynikki.blogspot.jp/2013/01/net-or.htmlhttp://ivis-mynikki.blogspot.jp/2014/03/blog-post.html
http://blog.micic.ch/net/easy-mvvm-example-with-inotifypropertychanged-and-inotifydataerrorinfo