title: Exception validating data with IDataErrorInfo with a MVVM implementation
body: <p>I'm trying to validate data in my MVVM application using IDataErrorInfo, but I'm running into some problems.</p>
  
  <p>When I set my TextBox with an invalid value, the validation works fine. But after I set the value of the TextBox to a valid value and I get this exception:</p>
  
  <pre><code>A first chance exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll
  A first chance exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll
  System.Windows.Data Error: 16 : Cannot get 'Item[]' value (type 'ValidationError') from '(Validation.Errors)' (type 'ReadOnlyObservableCollection`1'). BindingExpression:Path=(0).[0].ErrorContent; DataItem='TextBox' (Name='txtRunAfter'); target element is 'TextBox' (Name='txtRunAfter'); target property is 'ToolTip' (type 'Object') TargetInvocationException:'System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---&gt; System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
  Parameter name: index
      at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
      at System.ThrowHelper.ThrowArgumentOutOfRangeException()
      at System.Collections.Generic.List`1.get_Item(Int32 index)
      at System.Collections.ObjectModel.Collection`1.get_Item(Int32 index)
      at System.Collections.ObjectModel.ReadOnlyCollection`1.get_Item(Int32 index)
      --- End of inner exception stack trace ---
      at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct&amp; sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
      at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
      at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
      at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
      at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
      at MS.Internal.Data.PropertyPathWorker.GetValue(Object item, Int32 level)
      at MS.Internal.Data.PropertyPathWorker.RawValue(Int32 k)'
  </code></pre>
  
  <p>Here is the code for the view:</p>
  
  <pre><code>    &lt;UserControl x:Class="Telbit.TeStudio.View.Controls.TestStepListingStepView"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Background="{Binding BackgroundColor}"&gt;
  
      &lt;UserControl.Resources&gt;
          &lt;Style x:Key="TestStepTextBox" TargetType="{x:Type TextBox}"&gt;
              &lt;Setter Property="Background" Value="Transparent" /&gt;
              &lt;Setter Property="BorderThickness" Value="1"/&gt;
              &lt;Setter Property="BorderBrush" Value="Transparent"/&gt;
              &lt;Setter Property="VerticalContentAlignment" Value="Center"/&gt;
              &lt;Setter Property="HorizontalContentAlignment" Value="Left"/&gt;
              &lt;Setter Property="TextElement.FontSize" Value="10"/&gt;
              &lt;Setter Property="TextElement.FontWeight" Value="Regular"/&gt;
              &lt;Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/&gt;
              &lt;Setter Property="Template"&gt;
                  &lt;Setter.Value&gt;
                      &lt;ControlTemplate TargetType="{x:Type TextBox}"&gt;
                          &lt;Border x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"&gt;
                              &lt;ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/&gt;
                          &lt;/Border&gt;
                          &lt;ControlTemplate.Triggers&gt;
                              &lt;Trigger Property="IsMouseOver" Value="true"&gt;
                                  &lt;Setter Property="BorderBrush" Value="#3d62a9"/&gt;
                              &lt;/Trigger&gt;
                              &lt;Trigger Property="IsFocused" Value="true"&gt;
                                  &lt;Setter Property="BorderBrush" Value="#3d62a9"/&gt;
                                  &lt;Setter Property="Background" Value="White"/&gt;
                              &lt;/Trigger&gt;
                              &lt;Trigger Property="Validation.HasError" Value="true"&gt;
                                  &lt;Setter Property="ToolTip"
                                      Value="{Binding RelativeSource={RelativeSource Self}, 
                                      Path=(Validation.Errors)[0].ErrorContent}"/&gt;
                                  &lt;Setter Property="Background" Value="#33FF342D"/&gt;
                                  &lt;Setter Property="BorderBrush" Value="#AAFF342D"/&gt;
                              &lt;/Trigger&gt;
                          &lt;/ControlTemplate.Triggers&gt;
                      &lt;/ControlTemplate&gt;
                  &lt;/Setter.Value&gt;
              &lt;/Setter&gt;
          &lt;/Style&gt;
      &lt;/UserControl.Resources&gt;
  
      ...
  
      &lt;TextBox Name="txtRunAfter" Grid.Column="4" Text="{Binding RunAfter, ValidatesOnDataErrors=True, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource TestStepTextBox}"
           LostFocus="TextBoxLostFocus" PreviewKeyDown="TextBoxPreviewKeyDown" PreviewTextInput="TextBoxPreviewTextInput"/&gt;
  
      ...
  
   &lt;/UserControl&gt;
  </code></pre>
  
  <p>And here is the Code for the ViewModel:</p>
  
  <pre><code>class TestStepListingStepViewModel : ViewModelBase, IDataErrorInfo
  {
      private int _runAfter = 0;
      public int RunAfter
      {
          get
          {
              return _runAfter;
          }
  
          set
          {
              if (_runAfter != value)
              {
                  _runAfter = value;
                  OnPropertyChanged("RunAfter");
              }
          }
      }
  
  string IDataErrorInfo.Error
      {
          get { return null; }
      }
  
      string IDataErrorInfo.this[string columnName]
      {
          get
          {
              string message = null;
              if (columnName == "RunAfter")
                  message = validateRunAfter();
  
              return message;
          }
      }
  
      private string validateRunAfter()
      {
          if (_runAfter &gt;= _order)
              return "Run After value must be less than its Step Order (#) value.";
  
          return null;
      }
  }
  </code></pre>
  
  <p>I'm trying to figure out what's wrong with this for two days! Can some one with a pair of fresh eyes figure it out?</p>
  
  <p>EDIT:
  Here is the code of the TextBoxs handlers:</p>
  
  <pre><code>public partial class TestStepListingStepView : UserControl
  {
      private string mInvalidCharPattern = "[^0-9]";
  
      public TestStepListingStepView()
      {
          InitializeComponent();
  
          DataObject.AddPastingHandler(this.txtRunAfter, new DataObjectPastingEventHandler(TextBoxPasting));
      }
  
      private void TextBoxLostFocus(object sender, RoutedEventArgs e)
      {
          TextBox txt = sender as TextBox;
  
          if (txt != null &amp;&amp; string.IsNullOrEmpty(txt.Text))
              txt.Text = "0";
      }
  
      // Catch the space character, since it doesn't trigger PreviewTextInput
      private void TextBoxPreviewKeyDown(object sender, KeyEventArgs e)
      {
          if (e.Key == Key.Space) { e.Handled = true; }
      }
  
      // Do most validation here
      private void TextBoxPreviewTextInput(object sender, TextCompositionEventArgs e)
      {
          if (ValidateTextInput(e.Text) == false) { e.Handled = true; }
      }
  
      // Prevent pasting invalid characters
      private void TextBoxPasting(object sender, DataObjectPastingEventArgs e)
      {
          string lPastingText = e.DataObject.GetData(DataFormats.Text) as string;
          if (ValidateTextInput(lPastingText) == false) { e.CancelCommand(); }
      }
  
      // Do the validation in a separate function which can be reused
      private bool ValidateTextInput(string aTextInput)
      {
          if (aTextInput == null) { return false; }
  
          Match lInvalidMatch = Regex.Match(aTextInput, this.mInvalidCharPattern);
          return (lInvalidMatch.Success == false);
      }
  
  }
  </code></pre>
  
  <p>Also, I'm using version 3.5 of the .Net Framework.
  My application is very complex so I won't be able to create a small project that recreates only this part. My hope is that some of you already had this problem and know how to solve it.</p>
  
  <p>Thanks again everyone!</p>