您可能对此答案感兴趣:https ://stackoverflow.com/a/13335971/1094526
主要思想正是您所说的(订阅错误处理程序)。据我了解,问题是您无法从 ViewModel 访问控件,但这并不难解决
在我正在工作的项目中,我从 ViewModel 中公开了两个方法:AddUIError 和 RemoveUIError。我在 View 中创建了一个事件处理程序,并将 DataContext 转换为 ViewModel 的类型,并根据发生的情况调用 AddUIError 或 RemoveUIError。我正在使用 DataTemplates 将 View 与 ViewModel 相关联,因此在应用模板时,DataContext 会自动设置为 ViewModel。如果需要,您可以将 ViewModel 存储在私有字段中(在视图中)并在每次 DataContext 更改时更新引用(有一个 DataContextChanged 事件)
如果这将在多个 ViewModel 中完成,您可以将这两个方法(AddUIError 和 RemoveUIError)放在 ViewModelBase 之类的类中,并将 ValidationError 事件处理移动到一个 Behavior 并在每个视图中使用它。
有关行为部分的更多信息:行为类是 Expression Blend SDK 的一部分,因此如果您想遵循这种方式,您将需要它。
例如,行为对于将一些通用功能附加到许多组件而无需创建派生类很有用。
首先,我们需要在一个名为 ViewModelBase 的类中定义 AddUIError 和 RemoveUIError(当然,它是所有其他 ViewModel 的基类):
class ViewModelBase {
public void AddUIError(...) {/* Details ommitted */ }
public void RemoveUIError(...) {/* Details ommitted */ }
}
然后,通过子类化 Behavior 创建一个 Behavior。我们使用 FrameworkElement 作为模板参数,因此可以将此行为附加到任何 FrameworkElement(或派生类)实例:
class NotifyDataErrorsBehavior : Behavior<FrameworkElement>
{
// Called when the the Behavior is attached
protected override void OnAttached()
{
base.OnAttached();
// Initialize the handler for the Validation Error Event
_handler = new RoutedEventHandler(OnValidationRaised);
// Add the handler to the event from the element which is attaching this behavior
AssociatedObject.AddHandler(System.Windows.Controls.Validation.ErrorEvent, _handler);
}
protected override void OnDetaching()
{
base.OnDetaching();
// Remove the event handler from the associated object
AssociatedObject.RemoveHandler(System.Windows.Controls.Validation.ErrorEvent, _handler);
}
private RoutedEventHandler _handler = null;
private void OnValidationRaised(object sender, RoutedEventArgs e)
{
var args = (System.Windows.Controls.ValidationErrorEventArgs)e;
ViewModelBase viewModel = AssociatedObject.DataContext as ViewModelBase;
if (viewModel != null)
{
// You can add only Exception validation errors if you want..
if (args.Action == ValidationErrorEventAction.Added)
viewModel.AddUIValidationError(...);
else if (args.Action == ValidationErrorEventAction.Removed)
viewModel.RemoveUIValidationError(...);
else
throw new NotSupportedException("ValidationErrorEventAction has changed");
}
}
}
最后只在 XAML 中使用它: 1. 添加对 NotifyDataErrorsBehavior 所在命名空间的引用,以及对 System.Windows.Interactivity 命名空间的引用(来自 Expression Blend SDK):
<UserControl
...
xmlns:behavior="clr-namespace:MyApp.Behaviors"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
...
>
2. 添加行为(与您的 UserControl 的内容处于同一级别:
<i:Interaction.Behaviors>
<behavior:NotifyDataErrorsBehavior/>
</i:Interaction.Behaviors>
前任:
<UserControl
...
xmlns:behavior="clr-namespace:MyApp.Behaviors"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
...
>
<i:Interaction.Behaviors>
<behavior:NotifyDataErrorsBehavior/>
</i:Interaction.Behaviors>
<Grid>
...
</Grid>
</UserControl>