Лично мне не нравится использовать IDataErrorInfo для чего-то такого простого, потому что это требует бесполезного создания ViewModels и большого количества дополнительного кода, где ни один не должен быть необходим. Это должно быть так просто:
У меня есть расширение разметки, которое позволяет мне создавать привязку с пользовательским кодом проверки, указанным как выражение C #. Это очень просто сделать, за исключением синтаксического анализатора C #: просто реализуйте ProvideValue (), создав MultiBinding, который использует конвертер и создает соответствующую структуру проверки. Это позволяет выражению проверки получать содержащий DataContext и указанный пользователем объект Binding в дополнение к проверяемому значению.
С помощью этого решения вы можете сделать что-то вроде этого:
BoundProperty="{my:ValidatedBinding
Path=SomeProperty,
ValidationExpression = context is TextBox ? (int)value>3 : (int)value<7,
Mode=TwoWay,
Converter=...
Вы можете легко адаптировать моё решение без синтаксического анализатора C #, создав выражение как лямбда-код в коде и ссылаясь на него с помощью x: Static:
public static reaonly Expression myValidatorExpression =
(object value, object context, BindingBase binding) =>
context is TextBox ? (int)value>3 : (int)value<7;
...
ValidationExpression={x:Static local:MyClass.myValidatorExpression}
В общем, я считаю эту технику проще и понятнее, чем использование ViewModels. Я все еще использую ViewModels, когда требуется сложное преобразование, в противном случае просто чистый XAML прямо на уровень бизнес-объектов.
Обратите внимание, что при таком подходе предполагается, что уровень бизнес-объектов не привязан к какой-либо конкретной структуре внутреннего хранилища (например, структура таблицы SQL). Если бы это было так, изменение внутреннего хранилища потребовало бы изменения моего пользовательского интерфейса, и это также было бы нежелательно, поэтому с этой точки зрения было бы желательно ViewModel. Но если нет, я всегда предпочитаю, чтобы это было просто и просто использовать XAML.