Hi Sarah,
try following demo:
XAML:
<Window x:Class="WpfApp1.Window112"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp112"
mc:Ignorable="d"
Title="Sarah-3412_220303" Height="450" Width="800">
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<Window.Resources>
<!-- Error Template to change the default behaviour -->
<ControlTemplate x:Key="ErrorTemplate">
<DockPanel LastChildFill="True">
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder />
</Border>
</DockPanel>
</ControlTemplate>
<!-- To display tooltip with the error-->
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel DataContext="{Binding Data}">
<TextBox Text="{Binding Path=Firstname, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"
Validation.ErrorTemplate="{StaticResource ErrorTemplate}"/>
</StackPanel>
</Window>
and code:
using System;
using System.ComponentModel;
using System.Windows;
namespace WpfApp112
{
public class ViewModel
{
public ContactModel Data { get; set; } = new ContactModel();
}
public partial class ContactModel
{
public string Firstname { get; set; }
}
public partial class ContactModel : IDataErrorInfo
{
public string this[string columnName] => (string.IsNullOrEmpty(Firstname)) ? "Please enter value" : "";
public string Error { get => String.Empty; }
}
}
Result: