title: WPF DataGrid validation/binding mode bug
body: <p>I created a new project, very simple, to test only the Microsoft WPF DataGrid behavior. Nothing else involved, I only use the standard DataGrid:</p>
  
  <p><img src="https://i.stack.imgur.com/stoCS.png" alt="solution"></p>
  
  <pre><code>&lt;Window x:Class="MainWindow"
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
           xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
           xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
           mc:Ignorable="d" 
           d:DesignHeight="300" d:DesignWidth="300"&gt;
  
      &lt;DataGrid ItemsSource="{Binding Employees, Mode=TwoWay}"
                x:Name="tlv"
                AutoGenerateColumns="False"
                SelectionMode="Extended"
                CanUserAddRows="true"
                SelectionUnit="CellOrRowHeader"&gt;
          &lt;DataGrid.Columns&gt;
              &lt;DataGridTextColumn Header="First Name" Binding="{Binding FirstName, Mode=TwoWay}"/&gt;
              &lt;DataGridTextColumn Header="Last Name" Binding="{Binding LastName, Mode=TwoWay}"/&gt;
              &lt;DataGridTextColumn Header="Salary" Binding="{Binding Salary, Mode=TwoWay, ValidatesOnDataErrors=True, UpdateSourceTrigger=LostFocus}"/&gt;
          &lt;/DataGrid.Columns&gt;
      &lt;/DataGrid&gt;
  &lt;/Window&gt;
  </code></pre>
  
  <p>Code behind:</p>
  
  <pre><code>Imports System.Collections.ObjectModel
  Imports DataGridTest.Data
  
  Class MainWindow
  Sub New()
  
      ' This call is required by the designer.
      InitializeComponent()
  
      ' Add any initialization after the InitializeComponent() call.
      Me.DataContext = Me
      Employees = New ObservableCollection(Of Employee)(EmployeeRepository.GetFlatListData())
      BindableSelectedItems = New ObservableCollection(Of Object)
  End Sub
  
  
  Private _employees As ObservableCollection(Of Employee)
  
  Public Property Employees() As ObservableCollection(Of Employee)
      Get
          Return _employees
      End Get
      Set(ByVal value As ObservableCollection(Of Employee))
          _employees = value
      End Set
  End Property
  
  
  Private _bindableSelectedItems As ObservableCollection(Of Object)
  Public Property BindableSelectedItems() As ObservableCollection(Of Object)
      Get
          Return _bindableSelectedItems
      End Get
      Set(value As ObservableCollection(Of Object))
          'Set the new value of BindableSelectedItems
          _bindableSelectedItems = value
      End Set
  End Property
  
  
  Private _selectedEmployeeForSelectedItemsSimulation As Employee
  Public Property SelectedEmployeeForSelectedItemsSimulation() As Employee
      Get
          Return _selectedEmployeeForSelectedItemsSimulation
      End Get
      Set(value As Employee)
          'Set the new value of SelectedEmployeeForSelectedItemsSimulation
          _selectedEmployeeForSelectedItemsSimulation = value
  
          If _selectedEmployeeForSelectedItemsSimulation IsNot Nothing AndAlso BindableSelectedItems IsNot Nothing Then
              BindableSelectedItems.Clear()
              BindableSelectedItems.Add(value)
          End If
      End Set
  End Property
  End Class
  </code></pre>
  
  <p>The Employee class, which implements IDataErrorInfo:</p>
  
  <pre><code>Imports Microsoft.Practices.Prism.ViewModel
  Imports System.Collections.ObjectModel
  Imports System.ComponentModel
  
  Namespace Data
  Public Class Employee
      Inherits NotificationObject
      Implements IDataErrorInfo
  
      Public Sub New()
  
      End Sub
  
      Public Sub New(ByVal fName As String, ByVal lName As String, ByVal salary As Double)
          FirstName = fName
          LastName = lName
          Me.Salary = salary
      End Sub
  
  
      Private _firstName As String
      Public Property FirstName() As String
          Get
              Return _firstName
          End Get
          Set(value As String)
              'Set the new value of FirstName
              _firstName = value
  
              'Warn any Observers that the FirstName have changed.
              RaisePropertyChanged(Function() Me.FirstName)
          End Set
      End Property
  
  
      Private _lastName As String
      Public Property LastName() As String
          Get
              Return _lastName
          End Get
          Set(value As String)
              'Set the new value of LastName
              _lastName = value
  
              'Warn any Observers that the LastName have changed.
              RaisePropertyChanged(Function() Me.LastName)
          End Set
      End Property
  
  
      Private _isSelected As Boolean
      Public Property IsSelected() As Boolean
          Get
              Return _isSelected
          End Get
          Set(value As Boolean)
              'Set the new value of IsSelected
              _isSelected = value
  
              'Warn any Observers that the IsSelected have changed.
              RaisePropertyChanged(Function() Me.IsSelected)
          End Set
      End Property
  
      Private _salary As Double
      Public Property Salary() As Double
          Get
              Return _salary
          End Get
          Set(value As Double)
              'Set the new value of Salary
              _salary = value
  
              'Warn any Observers that the Salary have changed.
              RaisePropertyChanged(Function() Me.Salary)
          End Set
      End Property
  
  
  
      Public ReadOnly Property [Error] As String Implements IDataErrorInfo.Error
          Get
              Return String.Empty
          End Get
      End Property
  
      Default Public ReadOnly Property Item(columnName As String) As String Implements IDataErrorInfo.Item
          Get
  
              If Me.Salary &lt;= 0 Then
                  Return "The salary must be positive."
              End If
  
              Return String.Empty
          End Get
      End Property
  End Class
  End Namespace
  </code></pre>
  
  <p>So far, so good. Then, here is what happens when I try to update the salary value after having added a new row:</p>
  
  <p><img src="https://i.stack.imgur.com/BRHGy.gif" alt="enter image description here"></p>
  
  <p>The value resets to 0!</p>
  
  <ol>
  <li>Why is it doing this? Something wrong with the way I am using DataGrids?</li>
  <li>Is there a workaround?</li>
  </ol>
  
  <p><strong>[EDIT] ... and WORKAROUND</strong></p>
  
  <p>I finally found what looks like a workaround, even if I still don't know the reason of what I now consider as a bug in the Microsoft DataGrid. </p>
  
  <p><strong>If a binding mode is specified</strong> in the datagrid column <strong>with a Validation</strong>, <strong>the bug occurs</strong>; <strong>if</strong> instead <strong>I do not specify the binding mode, everything is fine</strong>.</p>
  
  <pre><code>&lt;DataGridTextColumn Header="Salary" Binding="{Binding Salary, ValidatesOnDataErrors=True, UpdateSourceTrigger=LostFocus}"/&gt;
  </code></pre>
  
  <p>What I do not quite understand though, is that as far as I know the default binding mode is TwoWay... Well, at least I solved my problem.</p>
  
  <p>I opened a bug report on Microsoft Connect, <a href="https://connect.microsoft.com/VisualStudio/feedbackdetail/view/946084/wpf-datagrid-specifying-binding-mode-with-validation-resets-cells" rel="nofollow noreferrer">here</a></p>