michelqa
michelqa

Reputation: 157

How to skip wpf validation when the model is initialized?

I'm trying to create a wpf error validation for a textbox. Looks pretty simple but after days and trying many methods I'm still trying to figure out the proper way to do this.

Here is my code (this is not my real code, just an example):

The textbox

<TextBox Text="{Binding Model.Name , UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}" 
        Style="{StaticResource NameTextBoxStyle}" />

The style

<Style x:Uid="Style_81" x:Key="NameTextBoxStyle}" TargetType="{x:Type TextBox}">
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="True">
        <Trigger.Setters>
            <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self},Path=              (Validation.Errors)[0].ErrorContent}"/>
        </Trigger.Setters>
        </Trigger>
    </Style.Triggers>
</Style>

The class

Public Class SomeClass
{
    public bool IsNameMandatory { get; set; }

    string name;
    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            if (IsNameMandatory && String.IsNullOrEmpty(value))
            {
                throw new Exception("Name can not be empty.");
            }
            if (value.Length > 12)
            {
                throw new Exception("name can not be longer than 12 charectors");
            }

            name = value;
            OnPropertyChanged("Name");
        }
    }
}

The problem: The error validation is working but when the model is "initialized" and set a blank value to "Name" an exception is raised with a messagebox instead of the red rectangle with the tooltip. I don't want to display the exception in a messagebox.

My needs: I need to validate the error only on LostFocus of the textbox and on demand

Upvotes: 0

Views: 1707

Answers (1)

Dean Kuga
Dean Kuga

Reputation: 12119

Here is how WPF validation is properly done using Binding.ValidationRules Property:

In your View:

xmlns:tools="clr-namespace:SomeAppNameSpace.Tools"

<TextBox Style="{StaticResource SomeStyle}">
    <TextBox.Text>
        <Binding Path="SomeProperty" UpdateSourceTrigger="LostFocus" >
            <Binding.ValidationRules>
                <tools:SomeValidationRule />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

ValidationRule class located in your tools (or equivalent of) namespace:

public class SomeValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, 
      CultureInfo cultureInfo)
    {
        var userText = value as string;
        return String.IsNullOrWhiteSpace(userText) ? 
            new ValidationResult(false, "Value must be provided.") : 
            new ValidationResult(true, null);
    }
}

So, this simple ValidationRule checks the textbox on LostFocus and if the textbox is left empty it returns a validation error message...

Last piece of the puzzle is that your "SomeStyle" which is the style for the textbox above must have Validation.ErrorTemplate defined... something like this:

<Style x:Key="SomeStyle" TargetType="{x:Type TextBox}">
<Setter Property="Validation.ErrorTemplate">
  <Setter.Value>
    <ControlTemplate >
      <!-- Your Error Template here. Typically a border with 
           red background and a textbox with light colored text...  -->
    </ControlTemplate>
  </Setter.Value>
</Setter>
</Style>

Upvotes: 2

Related Questions