How to use IDataErrorInfo with ObservableCollection?

Sarah 186 Reputation points
2022-03-03T11:34:16.93+00:00

Based on this demo how-to-update-database-automatically-from-obervabl.html, I extended the "ViewModel" class so that it now inherits from the "IDataErrorInfo" interface and made the following adjustments. Unfortunately, this did not work. Can someone say where the error is?

Code:

public class ViewModel : INotifyPropertyChanged, IDataErrorInfo  
 {  
	.  
	.  
	.	  
	   
	private ContactModel contact = new ContactModel();  
  
	public string Firstname => contact.Firstname;  
	public string Lastname => contact.Lastname;  
	public string Address => contact.Address;  
	public string Phone => contact.City;  
	public string Phone => contact.Phone;  
	public string Email => contact.Email;  
	public DateTime Birthday => contact.Birthday;  
	public string Specialty => contact.Specialty;  
  
    public Dictionary<string, string> ErrorCollection { get; private set; } = new Dictionary<string, string>();  
      
    public string Error  
    {  
    	get  
    	{  
    		return null;  
    	}  
    }  
      
    public string this[string propertyName]  
    {  
    	get  
    	{  
    		string result = null;  
      
    		switch (propertyName)  
    		{  
    			case "Firstname":  
    				if (string.IsNullOrWhiteSpace(Firstname))  
    					result = "Firstname cannot be empty";  
      
    				else if (Firstname.Length < 5)  
    					result = "Firstname must be a minimum of 5 characters.";  
      
    				break;  
    		}  
      
    		if (ErrorCollection.ContainsKey(propertyName))  
    		{  
    			ErrorCollection[propertyName] = result;  
    		}  
    		else if (result != null)  
    		{  
    			ErrorCollection.Add(propertyName, result);  
    		}  
      
    		OnPropertyChanged("ErrorCollection");  
      
    		return result;  
    	}  
    }  
 }  
public class ContactModel  
{  
	public int Id { get; set; }  
	public string Firstname { get; set; }  
	public string Lastname { get; set; }  
	public string Address { get; set; }  
	public string Phone { get; set; }  
	public string Phone { get; set; }  
	public string Email { get; set; }  
	public DateTime Birthday { get; set; }  
	public string Specialty { get; set; }  
  
 }  
  

XAML

<TextBox Height="35" Width="300" Text="{Binding Path=Firstname, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" ToolTip="{Binding ErrorCollection[Firstname]}"/>  
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,710 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Peter Fleischer (former MVP) 19,316 Reputation points
    2022-03-03T12:18:32.863+00:00

    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:

    179580-x.gif