You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VBA中ModelClass的Property Let内处理数据输入错误并通知ViewClass的最佳方法

嘿,针对你在VBA的ModelClass里想在Property Let中通知ViewClass数据输入错误的需求,我整理了几个在VBA环境下非常实用的最佳方案,一起来看看:

方案1:自定义事件(推荐,解耦首选)

这是MVVM模式下最常用的解耦方式,Model只负责触发事件,View负责订阅并处理事件,两者之间不需要直接依赖具体实现。

步骤1:在ModelClass中定义事件

在ModelClass的声明部分添加自定义事件,用来传递错误信息和对应的属性名:

Option Compare Database
Option Explicit
Private m_idCompra As String

' 定义验证错误事件,传递错误信息和属性名称
Public Event ValidationError(message As String, propertyName As String)
' 定义属性更新成功事件(可选,通知View数据已更新)
Public Event PropertyUpdated(propertyName As String, newValue As Variant)

Public Property Get codCompra() As String
    codCompra = m_idCompra
End Property

Public Property Let codCompra(ByVal codigoCompra As String)
    If Len(codigoCompra) = 0 Then
        ' 触发错误事件,传递错误信息和属性名
        RaiseEvent ValidationError("采购编码不能为空!", "codCompra")
    ElseIf Not IsNumeric(codigoCompra) Then
        RaiseEvent ValidationError("采购编码必须为数字格式!", "codCompra")
    Else
        m_idCompra = codigoCompra
        ' 可选:触发属性更新成功事件
        RaiseEvent PropertyUpdated("codCompra", codigoCompra)
    End If
End Property

步骤2:在ViewClass中订阅事件

在ViewClass里用WithEvents声明Model实例,然后编写事件处理过程:

Option Compare Database
Option Explicit
' 用WithEvents声明,才能订阅Model的事件
Private WithEvents m_model As ModelClass

Public Sub Initialize(model As ModelClass)
    Set m_model = model
End Sub

' 处理Model的验证错误事件
Private Sub m_model_ValidationError(message As String, propertyName As String)
    ' 这里写View的处理逻辑,比如弹出提示、高亮输入框等
    MsgBox "输入错误:" & message, vbExclamation, "验证失败"
    ' 示例:如果View有对应控件,可以定位到错误控件
    ' Me.txtCodCompra.SetFocus
End Sub

' 处理属性更新成功事件(可选)
Private Sub m_model_PropertyUpdated(propertyName As String, newValue As Variant)
    ' 比如更新View上的显示
    ' Me.txtCodCompra.Value = newValue
End Sub

这种方式的好处是Model和View完全解耦,Model不需要知道View的具体类型,只要触发事件就行,扩展性很强。


方案2:回调函数(适合简单一对一场景)

如果你的场景比较简单,Model和View是一对一绑定的,可以让View把一个回调方法传递给Model,Model在出错时直接调用这个方法。

步骤1:在ModelClass中添加回调引用

Option Compare Database
Option Explicit
Private m_idCompra As String
' 保存View的回调对象
Private m_validationCallback As Object

' 让View设置回调对象
Public Property Set ValidationCallback(obj As Object)
    Set m_validationCallback = obj
End Property

Public Property Get codCompra() As String
    codCompra = m_idCompra
End Property

Public Property Let codCompra(ByVal codigoCompra As String)
    If Len(codigoCompra) = 0 Then
        ' 调用View的回调方法
        If Not m_validationCallback Is Nothing Then
            m_validationCallback.OnValidationError "采购编码不能为空!", "codCompra"
        End If
    ElseIf Not IsNumeric(codigoCompra) Then
        If Not m_validationCallback Is Nothing Then
            m_validationCallback.OnValidationError "采购编码必须为数字格式!", "codCompra"
        End If
    Else
        m_idCompra = codigoCompra
        ' 可选:调用更新成功的回调
        If Not m_validationCallback Is Nothing Then
            m_validationCallback.OnPropertyUpdated "codCompra", codigoCompra
        End If
    End If
End Property

步骤2:在ViewClass中实现回调方法

Option Compare Database
Option Explicit
Private m_model As ModelClass

Public Sub Initialize(model As ModelClass)
    Set m_model = model
    ' 把自己设置为Model的回调对象
    Set m_model.ValidationCallback = Me
End Sub

' 实现Model需要的回调方法
Public Sub OnValidationError(message As String, propertyName As String)
    MsgBox "输入错误:" & message, vbExclamation, "验证失败"
    ' 其他View处理逻辑
End Sub

Public Sub OnPropertyUpdated(propertyName As String, newValue As Variant)
    ' 更新View显示
End Sub

这个方案实现起来更简单,但耦合度比事件高一点,适合小型项目或者简单的界面场景。


方案3:抛出自定义错误(适合需要中断流程的场景)

如果希望在输入错误时直接中断赋值流程,并且让View处理错误,可以抛出自定义错误,然后View在赋值时捕获错误。

步骤1:在ModelClass中抛出错误

Option Compare Database
Option Explicit
Private m_idCompra As String

Public Property Get codCompra() As String
    codCompra = m_idCompra
End Property

Public Property Let codCompra(ByVal codigoCompra As String)
    If Len(codigoCompra) = 0 Then
        ' 抛出自定义错误,错误码用vbObjectError + 自定义编号(避免和系统错误冲突)
        Err.Raise vbObjectError + 1001, "ModelClass.codCompra", "采购编码不能为空!"
    ElseIf Not IsNumeric(codigoCompra) Then
        Err.Raise vbObjectError + 1002, "ModelClass.codCompra", "采购编码必须为数字格式!"
    Else
        m_idCompra = codigoCompra
    End If
End Property

步骤2:在ViewClass中捕获错误

Option Compare Database
Option Explicit
Private m_model As ModelClass

Public Sub AssignCodCompra(value As String)
    On Error GoTo ErrorHandler
    m_model.codCompra = value
    ' 如果没有错误,执行成功逻辑
    MsgBox "编码设置成功!", vbInformation
    Exit Sub

ErrorHandler:
    ' 处理错误信息
    MsgBox "输入错误:" & Err.Description, vbExclamation, "验证失败"
    ' 可以根据错误码做不同处理
    Select Case Err.Number
        Case vbObjectError + 1001
            Me.txtCodCompra.SetFocus
        Case vbObjectError + 1002
            Me.txtCodCompra.SelStart = 0
            Me.txtCodCompra.SelLength = Len(Me.txtCodCompra.Text)
    End Select
End Sub

这种方式适合需要严格中断流程的场景,但Model和View的耦合度也比较高,因为View需要知道Model的错误码或者错误信息格式。


最后总结一下:

  • 如果追求解耦和扩展性,优先选自定义事件方案;
  • 如果是简单场景,选回调函数更快捷;
  • 如果需要中断流程并强制处理错误,选抛出自定义错误。

内容的提问来源于stack exchange,提问作者Alex Boorjs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 09:22:41