この回答に興味があるかもしれません: https://stackoverflow.com/a/13335971/1094526
主なアイデアはまさにあなたが言ったことです (エラーハンドラーにサブスクライブします)。私が理解しているように、問題はViewModelからコントロールにアクセスできないことですが、解決するのは難しくありません
私が取り組んでいるプロジェクトでは、ViewModel から AddUIError と RemoveUIError の 2 つのメソッドを公開しました。ビューでイベント ハンドラーを作成し、そこで DataContext をビューモデルの型にキャストし、何が起こったかに応じて AddUIError または RemoveUIError を呼び出します。View を ViewModel に関連付けるために DataTemplates を使用しているため、テンプレートが適用されると、DataContext が自動的に ViewModel に設定されます。必要に応じて、ViewModel をプライベート フィールド (ビュー内) に格納し、DataContext が変更されるたびに参照を更新できます (DataContextChanged イベントがあります)。
これを複数の ViewModel で行う場合は、両方のメソッド (AddUIError と RemoveUIError) を ViewModelBase などのクラスに配置し、ValidationError イベント処理を Behavior に移動して、各ビューで使用できます。
動作部分に関する詳細: 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>