繁体   English   中英

如何捕获PropertyChanged事件期间抛出的异常

[英]How to catch an exception thrown during a PropertyChanged event

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

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

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

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

你走错了路。

在MVVM中处理验证的一种好方法是在绑定上实现IDataErrorInfo并将ValidatesOnDataErrors设置为true 您几乎肯定也希望启用ValidatesOnExceptions以获得完整性,并且NotifyOnValidationError使绑定引擎在您绑定属性的控件上触发Validation.Error附加事件。

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

一些技巧:

  • .NET 4.5引入了INotifyDataErrorInfo和相应的ValidatesOnNotifyDataErrors绑定属性,与IDataErrorInfo相比,它提供了增强的验证功能。 你可能想调查一下。
  • 您不需要在IDataErrorInfo.Error实际执行任何有意义的操作,因为它由Windows Forms基础结构使用并在WPF中被忽略。 你甚至可以让getter抛出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.Handledtrue以便链被停止。
  5. 验证错误将返回到视图。

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

IDataErrorInfo / INotifyDataErrorInfo实际上没有什么可以做的,因为你如何实现它们完全取决于你。 对于更多示例,请务必查看后者文档的Silverlight版本 ; 也有很多有用的材料, 这样在互联网上。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM