I have took the following approach and it works. Basically, the Model should rightfully record errors and have them listed up in a dictionary, even if the object is just instantiated and User hasn't entered any Text yet. So I didn't change my Model code or the IDataErrorInfo validation code. Instead, I just set the Validation.Error Template property to {x:Null} initially. Then there is code to wire up the TextBox's LostFocus event that changes the Validation.Error template back to what I am using. In order to achieve the swapping of templates and attaching LostFocus event handler to all TextBox's in my application, I used a couple of dependency properties. Here is the code that I have used.
Dependency Properties and LostFocus Code:
public static DependencyProperty IsDirtyEnabledProperty = DependencyProperty.RegisterAttached("IsDirtyEnabled",
typeof(bool), typeof(TextBoxExtensions), new PropertyMetadata(false, OnIsDirtyEnabledChanged));
public static bool GetIsDirtyEnabled(TextBox target) {return (bool)target.GetValue(IsDirtyEnabledProperty);}
public static void SetIsDirtyEnabled(TextBox target, bool value) {target.SetValue(IsDirtyEnabledProperty, value);}
public static DependencyProperty ShowErrorTemplateProperty = DependencyProperty.RegisterAttached("ShowErrorTemplate",
typeof(bool), typeof(TextBoxExtensions), new PropertyMetadata(false));
public static bool GetShowErrorTemplate(TextBox target) { return (bool)target.GetValue(ShowErrorTemplateProperty); }
public static void SetShowErrorTemplate(TextBox target, bool value) { target.SetValue(ShowErrorTemplateProperty, value); }
private static void OnIsDirtyEnabledChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) {
TextBox textBox = (TextBox)dependencyObject;
if (textBox != null) {
textBox.LostFocus += (s, e) => {
if ((bool) textBox.GetValue(ShowErrorTemplateProperty) == false) {
textBox.SetValue(ShowErrorTemplateProperty, true);
}
};
}
}
If IsDirtyEnabled dependency property is set to true, it uses the callback to attach the TextBox's LostFocus event to a handler. The handler just changes the ShowErrorTemplate attached property to true, which in turn triggers in textbox's style trigger to show the Validation.Error template, when the TextBox loses focus.
TextBox Styles:
<Style TargetType="{x:Type TextBox}">
<Setter Property="Validation.ErrorTemplate" Value="{StaticResource ValidationErrorTemplate}"/>
<Setter Property="gs:TextBoxExtensions.IsDirtyEnabled" Value="True" />
<Style.Triggers>
<Trigger Property="gs:TextBoxExtensions.ShowErrorTemplate" Value="false">
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
</Trigger>
</Style.Triggers>
</Style>
This may seem too much of code for a simple thing, but then I have to do it only once for all the Textboxes I am using.
regards,
Nirvan.