I want to display a input-validation for the user when entering empty values in a text box, is there a simple way to use data annotation to do this for WPF ? 
I am new to WPF and C# if someone could explain this for me I would really appreciate it. 
I want something like this or similar : 

 
    
    - 7,396
- 13
- 38
- 57
 
    
    - 181
- 1
- 5
- 15
- 
                    1Here is a nice article: http://social.technet.microsoft.com/wiki/contents/articles/22660.data-validation-in-mvvm.aspx – Michał Komorowski Jul 13 '16 at 11:08
- 
                    Please show, what you have tried already – lokusking Jul 13 '16 at 11:16
- 
                    I tried something like this : (the first comment) http://stackoverflow.com/questions/19539492/wpf-textbox-validation-c-sharp , but it only displays a red line around the text box without any comment. – Little Programmer Jul 13 '16 at 11:46
- 
                    the second comment uses try and catch and they are very slow is there another way? – Little Programmer Jul 13 '16 at 11:59
- 
                    @LittleProgrammer see the article in the first comment to your question – Tim Pohlmann Jul 13 '16 at 12:05
3 Answers
Using a ValidationRule on your binding can get the effect you want, you specify them declaratively in your XAML, and you can make them as custom and complex as you need to:
<TextBox    x:Name="FilePathTextBox" Width="350" Margin="5,0,0,0">
    <TextBox.Text>
        <Binding Path="FilePath" UpdateSourceTrigger="PropertyChanged" >
            <Binding.ValidationRules>
                <this:FilePathValidationRule />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>
will produce this:
Reference my blog post Taking data binding, validation and MVVM to the next level
 
    
    - 49,403
- 14
- 95
- 145
You have to use ErrorTemplate like below : 
<TextBox...>
    <Validation.ErrorTemplate>
        <ControlTemplate>
            <StackPanel>
                <!-- Placeholder for the TextBox itself -->
                <AdornedElementPlaceholder x:Name="textBox"/>
                <TextBlock Text="{Binding [0].ErrorContent}" Foreground="Red"/>
            </StackPanel>
        </ControlTemplate>
    </Validation.ErrorTemplate>
</TextBox>
 
    
    - 9,647
- 1
- 26
- 38
Beside all the other correct answers here, additionally to ValidationRule, I'd recommend you to use  IDataError-Interface.
With that interface you can match more easily your use of DataAnnotations as you mentioned in the title.
Demo-Model:
 public class Pony : IDataErrorInfo, INotifyPropertyChanged {
    private Dictionary<string, List<string>> _errors = new Dictionary<string, List<string>>();
    [Range(0,4)]
    public int Id {
      get; set;
    }
    [Required]
    public string Name {
      get; set;
    }
    public Brush Color {
      get; set;
    }
    public string Error {
      get {
        var builder = new StringBuilder();
        foreach (var error in this.Errors) {
          if (error.Value.Count > 0) {
            foreach (var text in error.Value) {
              builder.AppendLine(text);
            }
          }
        }
        return builder.Length > 0 ? builder.ToString(0, builder.Length - 2) : builder.ToString();
      }
    }
    public bool HasError => this.Errors.Count > 0;
    public virtual string this[string columnName] {
      get {
        var modelClassProperties = TypeDescriptor.GetProperties(this.GetType());
        foreach (PropertyDescriptor prop in modelClassProperties) {
          if (prop.Name != columnName) {
            continue;
          }
          this.Errors[columnName] = new List<string>();
          foreach (var attribute in prop.Attributes) {
            if (!(attribute is ValidationAttribute)) {
              continue;
            }
            var validation = attribute as ValidationAttribute;
            if (validation.IsValid(prop.GetValue(this))) {
              continue;
            }
            var dn = prop.Name;
            foreach (var pa in prop.Attributes.OfType<DisplayNameAttribute>()) {
              dn = pa.DisplayName;
            }
            this.Errors[columnName].Add(validation.FormatErrorMessage(dn));
            this.OnPropertyChanged("Error");
            return validation.FormatErrorMessage(dn);
          }
        }
        this.Errors.Remove(columnName);
        this.OnPropertyChanged("Error");
        return null;
      }
    }
    internal Dictionary<string, List<string>> Errors => this._errors;
    public event PropertyChangedEventHandler PropertyChanged;
    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
      this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
  }
Demo-XAML
<Grid  VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Height="200">
        <Grid.Resources>
            <Style TargetType="{x:Type TextBox}">
                <Setter Property="MinWidth" Value="100"></Setter>
                <Setter Property="Validation.ErrorTemplate">
                    <Setter.Value>
                        <ControlTemplate>
                            <StackPanel>
                                <!-- Placeholder for the TextBox itself -->
                                <AdornedElementPlaceholder x:Name="textBox"/>
                                <TextBlock Text="{Binding [0].ErrorContent}" Foreground="Red"/>
                            </StackPanel>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            <Style TargetType="{x:Type WrapPanel}">
                <Setter Property="Margin" Value="0,0,0,10"></Setter>
            </Style>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <GroupBox Header="Pony 1" Grid.Row="1">
            <StackPanel>
                <WrapPanel>
                    <TextBlock Text="Id:"/>
                    <TextBox Text="{Binding Ponys[0].Id, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"></TextBox>
                </WrapPanel>
                <WrapPanel Grid.Row="1">
                    <TextBlock Text="Name:"/>
                    <TextBox Text="{Binding Ponys[0].Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"></TextBox>
                </WrapPanel>
                <WrapPanel Grid.Row="2">
                    <TextBlock Text="Color:"/>
                    <TextBox Text="{Binding Ponys[0].Color, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"></TextBox>
                </WrapPanel>
            </StackPanel>
        </GroupBox>
        <GroupBox Header="Pony 2">
            <StackPanel>
                <WrapPanel>
                    <TextBlock Text="Id:"/>
                    <TextBox Text="{Binding Ponys[1].Id, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"></TextBox>
                </WrapPanel>
                <WrapPanel Grid.Row="1">
                    <TextBlock Text="Name:"/>
                    <TextBox Text="{Binding Ponys[1].Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"></TextBox>
                </WrapPanel>
                <WrapPanel Grid.Row="2">
                    <TextBlock Text="Color:"/>
                    <TextBox Text="{Binding Ponys[1].Color, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"></TextBox>
                </WrapPanel>
            </StackPanel>
        </GroupBox>
    </Grid>
Demo-Usage:
public MainWindow() {
      InitializeComponent();     
      this.Ponys = new List<Pony>();
      this.Ponys.Add(new Pony() { Color = Brushes.HotPink });
      this.Ponys.Add(new Pony() { Id = 9, Name = "Not so fluffy", Color = Brushes.Chocolate });
      this.DataContext = this;
    }
Conclusion:
This Approach is designed to use in a Base-class.
It fully supports Attribute-Validation and is capable of handling multiple Attributes per Property.
Since ValidationAttribute is not sealed, you can inherit from it and design your own validations.
Example:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
  public class Numeric : ValidationAttribute {
    protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
      if (value == null) {
        return ValidationResult.Success;
      }
      double result;
      var isNumeric = double.TryParse(value.ToString(), out result);
      return !isNumeric ? new ValidationResult(this.ErrorMessage) : ValidationResult.Success;
    }
  }
I developed this, because i hated how i had to use the ValidationRules.
Additionally, the ValidationRules are only Input-Validations. This means, if your data is corrupt, you will never notice

