Черт, это заняло некоторое время, чтобы придумать, но, как всегда, ... привязал поведение к спасению.
По сути, вы смотрите на отслеживание грязного состояния. Есть много способов сделать это, используя вашу ViewModel, но, так как вы не хотели изменять свои сущности, лучший способ - использовать поведения.
Прежде всего удалите ValidatesOnDataErrors из вашей привязки Xaml. Создайте поведение для элемента управления, над которым вы работаете (как показано ниже для TextBox
), и в событии TextChanged
(или любом другом событии, которое вы хотите) сбросьте привязку на ту, которую действительно проверяет на данных ошибки. Просто на самом деле.
Таким образом, ваши сущности не должны меняться, ваш Xaml поддерживается в достаточно чистом состоянии, и вы получаете свое поведение.
Вот код поведения -
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace IDataErrorInfoSample
{
public static class DirtyStateBehaviours
{
public static string GetDirtyBindingProperty(DependencyObject obj)
{
return (string)obj.GetValue(DirtyBindingPropertyProperty);
}
public static void SetDirtyBindingProperty(DependencyObject obj, string value)
{
obj.SetValue(DirtyBindingPropertyProperty, value);
}
// Using a DependencyProperty as the backing store for DirtyBindingProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DirtyBindingPropertyProperty =
DependencyProperty.RegisterAttached("DirtyBindingProperty", typeof(string), typeof(DirtyStateBehaviours),
new PropertyMetadata(new PropertyChangedCallback(Callback)));
public static void Callback(DependencyObject obj,
DependencyPropertyChangedEventArgs args)
{
var textbox = obj as TextBox;
textbox.TextChanged += (o, s) =>
{
Binding b = new Binding(GetDirtyBindingProperty(textbox));
b.ValidatesOnDataErrors = true;
textbox.SetBinding(TextBox.TextProperty, b);
};
}
}
}
И Xaml тоже довольно прост.
<Window x:Class="IDataErrorInfoSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:IDataErrorInfoSample"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow"
Height="350"
Width="525">
<Window.DataContext>
<local:Person />
</Window.DataContext>
<StackPanel Margin="20">
<TextBox Height="20"
Margin="0,0,0,10"
local:DirtyStateBehaviours.DirtyBindingProperty="Name"
Text="{Binding Path=Name}">
</TextBox>
<Button Content="Go" />
</StackPanel>
HTH, Stimul8d.