0

我正在使用 MVC\MVVM 和 WPF。我有一个绑定到模型的表单和一个捕获 PropertyChanged 事件并评估业务规则和验证的控制器。好吧,我想在验证错误时弹出一条消息,告诉用户出了什么问题以及如何修复它。但我不确定控制器的“正确”方式。我想抛出一个可以被视图捕获的异常,但我不知道如何。我试过 Dispatcher.Invoke() 但这只是让我在应用程序级别出现未处理的异常。

如何捕获从 Controller 中的 PropertyChanged 事件处理程序生成的异常?

编辑:具体来说,我有一个组合框,其中包含折扣列表。我不能允许不适当的选择,但我必须通知用户选择不适当的原因。这不像其中包含整数的文本框那么明显。我需要告诉用户客户填写调查的日期。他们不能两次使用该折扣。我不想从列表中排除调查折扣,因为这对用户来说只是一个错误。我需要向他们展示折扣并告诉他们客户已使用该折扣并且不能再次使用它。

编辑 2:我查看了 ValidationRule 类,因为我必须使用数据库查找,所以我不知道如何将所有内容保留在模型中,并且仍然在控制器中保留业务规则。我查看了 IDataErrorInfo 但这需要我将模型包装在我的控制器中并绑定到控制器,但仅限于一个字段。我认为在这种情况下最好的做法是让控制器调用视图上的方法并弹出一条消息。

4

1 回答 1

2

你走错了路。

在 MVVM 中处理验证的一个好方法是在绑定上实现和设置IDataErrorInfo。您几乎肯定也希望启用完整性,以便绑定引擎触发您已将属性绑定到的控件上的附加事件。ValidatesOnDataErrorstrueValidatesOnExceptionsNotifyOnValidationErrorValidation.Error

有关更多详细信息,请参阅MSDN 文档中有关WPF中的数据绑定的验证部分。

一些技巧:

  • .NET 4.5 引入INotifyDataErrorInfo了相应的绑定属性,与;ValidatesOnNotifyDataErrors相比提供了增强的验证功能。IDataErrorInfo你可能想调查一下。
  • 您实际上不需要在内部做任何有意义的事情,IDataErrorInfo.Error因为它由 Windows 窗体基础结构使用并且在 WPF 中被忽略。您甚至可以使用 getter throw NotImplementedException
  • 这里这里有很好的阅读材料来说明这种方法,并附有示例和代码。

更新:澄清和示例代码

这个验证模型根本不涉及实现ValidationRule你自己;您的模型(即绑定源)只需要实现两个接口之一。如何实现接口完全取决于您;在过去的一个项目中,我实现了基本的异步验证

public interface IDelegatedValidation : IDataErrorInfo
{
    /// <summary>
    /// Occurs when validation is to be performed.
    /// </summary>
    event EventHandler<DelegatedValidationEventArgs> ValidationRequested;
}

public class DelegatedValidationEventArgs : EventArgs
{
    public DelegatedValidationEventArgs(string propertyName)
    {
        this.PropertyName = propertyName;
    }

    public string PropertyName { get; private set; }

    public bool Handled { get; set; }

    public string ValidationError { get; set; }
}

该模型IDelegatedValidation通过公开一个事件并使用

string IDataErrorInfo.this[string columnName]
{
    get { return this.GetValidationError(columnName); }
}

private string GetValidationError(string propertyName)
{
    var args = new DelegatedValidationEventArgs(propertyName);
    this.OnValidationRequested(args);
    return args.ValidationError;
}

protected virtual void OnValidationRequested(DelegatedValidationEventArgs args)
{
    var handler = this.ValidationRequested;
    if (handler == null) {
        return;
    }

    foreach (EventHandler<DelegatedValidationEventArgs> target in handler.GetInvocationList()) {
        target.Invoke(this, args);
        if (args.Handled) {
            break;
        }
    }
}

所以工作流程是这样的:

  1. 当模型即将被视图模型包装时,一些可以执行验证的适当实体订阅它的ValidationRequested事件。
  2. 视图绑定到模型;在某些时候触发验证。
  3. 该模型调用GetValidationError.
  4. 事件处理程序被一一调用;第一个产生验证错误的处理程序设置args.ValidationErrorargs.Handled停止true链。
  5. 验证错误返回到视图。

如果视图模型需要知道它的模型是否有效(例如启用/禁用“保存”命令),它还需要进入这个过程。

真的没有什么是你不能IDataErrorInfo/做的,INotifyDataErrorInfo因为你如何实现它们完全取决于你。一定要查看后者文档的Silverlight 版本以获取更多示例;互联网上也有很多类似的有用材料。

于 2012-10-01T15:30:39.800 回答