Очередной вопрос на MSDN. Стоит задача при редактировании записи сначала проверить данные, а только потом применить изменения к объекту модели. Я всю конструкцию MVVM воспроизводить не буду и покажу на примере в котором будет только один объект модели, а все остальное будет в лоб. Начнем.

Создаем пустой проект и добавляем в него два класса. Первый класс для модели:

class Person : DependencyObject

{
    public string LastName
    {
        get { return (string)GetValue(LastNameProperty); }
        set { SetValue(LastNameProperty, value); }
    }
 
    // Using a DependencyProperty as the backing store for LastName.  This enables animation, styling, binding, etc…
    public static readonly DependencyProperty LastNameProperty =
        DependencyProperty.Register(«LastName»typeof(string), typeof(Person), new PropertyMetadata(«»));
 
    public string FirstName
    {
        get { return (string)GetValue(FirstNameProperty); }
        set { SetValue(FirstNameProperty, value); }
    }
 
    // Using a DependencyProperty as the backing store for FirstName.  This enables animation, styling, binding, etc…
    public static readonly DependencyProperty FirstNameProperty =
        DependencyProperty.Register(«FirstName»typeof(string), typeof(Person), new PropertyMetadata(«»));
        
}
Для проверки добавляем класс чекающий строку на пустоту:

class NotEmptyValidation : ValidationRule
{
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        var result = new ValidationResult(false"Не допустима пустая строка");
        if (value is string && !string.IsNullOrWhiteSpace(value.ToString()))
        {
            result = new ValidationResult(truenull);
        }
        return result;
    }
}

Разметка формы:

<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication3"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <TextBox Text="{Binding Person.LastName}" />
        <TextBox Text="{Binding Person.FirstName}" Grid.Row="1" />
        <TextBox Grid.Column="2" x:Name="tbLastName">
            <TextBox.Text>
                <Binding Path="Person.LastName" UpdateSourceTrigger="Explicit">
                    <Binding.ValidationRules>
                        <local:NotEmptyValidation />
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
        <TextBox Grid.Row="1" Grid.Column="2" x:Name="tbFirstName">
            <TextBox.Text>
                <Binding Path="Person.FirstName" UpdateSourceTrigger="Explicit">
                    <Binding.ValidationRules>
                        <local:NotEmptyValidation />
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
        <Button Content="Принять" Click="Button_Click" Grid.Column="2" Grid.Row="2" />
    </Grid>
</Window>

Код формы:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        Loaded += MainWindow_Loaded;
    }

    public Person Person
    {
        get { return (Person)GetValue(PersonProperty); }
        set { SetValue(PersonProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Person.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty PersonProperty =
        DependencyProperty.Register("Person"typeof(Person), typeof(MainWindow), new PropertyMetadata(null));


    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        Person = new Person() { LastName = "Иванов" };
        this.DataContext = this;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        BindingExpression beLastName = tbLastName.GetBindingExpression(TextBox.TextProperty);
        BindingExpression beFirstName = tbFirstName.GetBindingExpression(TextBox.TextProperty);
        if (beLastName.ValidateWithoutUpdate() && beFirstName.ValidateWithoutUpdate())
        {
            beLastName.UpdateSource();
            beFirstName.UpdateSource();
            // Вот здесь можно закрывать View, не забыв уведомить ViewModel
        }
    }
}

Несколько комментариев:
1. Не забываем на форме подключить пространство имен где описан класс валидатора:
xmlns:local=«clr-namespace:WpfApplication3»
2. Для того, чтобы Binding не срабатывал сам, а только по кнопке, прописываем в нем:
UpdateSourceTrigger=«Explicit»
3. Перед принудительным применением Binding проверяем, а все ли нормально:
if (beLastName.ValidateWithoutUpdate() && beFirstName.ValidateWithoutUpdate())
4. Работает вот так. Запускаем:

Вводим слева значение и переводим фокус ввода, значение отображается справа:

Теперь вводим значение в правый TextBox и меняем фокус ввода:

Как видим, значение слева не обновилось. Нажимаем Принять:

Значение обновилось. Теперь значение меняем на некорректное (пустую строку) и нажимаем принять:

Видим подсветку ошибки и то, что в модель пустое значение не скопировалось.