Need help implementing INotifyDataErrorInfo with Fluent Validation and SfTextInputLayout with SfTextBoxExt

Hello Team,

Hope everyone is safe.

I need help implementing INotifyDataErrorInfo interface with SfTextBoxEx placed inside SfTextInputLayout. 

WPF with MVVM using Caliburn.Micro framework.

Please find following project structure to understand by question.

1)
FolderName : Infrastructure
File : ValidatedPropertyChangedBase.cs
--It contains implementation for INotifyDataErrorInfo.

2)
FolderName : Model
File : TestModel.cs
--Contains two properties with inherited from ValidatedPropertyChangedBase
--Also contains the class for Validation of properties using FluentValidation

4)
FolderName : View
File : HomeView.xaml
--Standard window with two SfTextInputLayout with SfTextBoxExt

4)
FolderName : ViewModel
File : HomeViewModel.cs
--standard view model with Model as property with Validation triggering.
--Here if i put breakpoint on validation method i can see that error returned is correct but somehow it is not triggering the UI to show the error message.
--I've already set ValidatesOnNotifyDataError=true while binding the property with textbox.

I am attaching the sample project which I made to show you demo. Please check and guide me if something is wrong.



Attachment: ValidationDemo_(2)_44d845c0.zip

9 Replies 1 reply marked as answer

SS Suganya Sethuraman Syncfusion Team May 25, 2021 01:15 PM UTC

Hi Dhairya,

Greetings from Syncfusion.

Currently, we are validating on this and we will update the full details on May 27, 2021. We appreciate your patience until then.

Regards,
Suganya Sethuraman.
 



DJ Dhairya Joshi May 27, 2021 01:06 PM UTC

Hello Suganya

Please provide update on this, as I was expecting some input early.


SS Suganya Sethuraman Syncfusion Team May 27, 2021 02:02 PM UTC

Hi Dhairya, 
  
Thanks for your patience.

We have analyzed the reported query. SfTextBoxExt supports FluentValidation. We were unable to validate when we used SfTextBoxExt within the SfTextInputLayout. We are currently checking with the SfTextInputLayout team on this. We will provide complete information on or before May 31, 2021. Until then, we appreciate your patience.
 
 
Regards,
Suganya Sethuraman.
 



SS Sridevi Sivakumar Syncfusion Team May 28, 2021 11:35 AM UTC

Hi Dhairya Joshi,

You can handle the validation by setting the SfTextInputLayout HasError property to true. We have modified the shared sample and added validation text in SfTextInputLayout ErrorText as per the below code snippet.

[XAML]: 
        <sf:SfTextInputLayout HasError="{Binding FirstNameHasError}" 
            Hint="First Name" ErrorText="Please enter first name"> 
            <sf:SfTextBoxExt 
                Text="{Binding Path=Model.FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, 
                ValidatesOnNotifyDataErrors=True}" /> 
        </sf:SfTextInputLayout> 
        <sf:SfTextInputLayout Margin="0,10,0,5" 
            Hint="Last Name" HasError="{Binding LastNameHasError}" ErrorText="Please enter last name"> 
            <sf:SfTextBoxExt 
                Text="{Binding Path=Model.FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True}" /> 
        </sf:SfTextInputLayout> 
  
[C#]: 
        public void ValidateData() 
        { 
            ClearAllErrors(); 
            var validator = new TestModelValidation(); 
            FluentValidation.Results.ValidationResult result = validator.Validate(Model); 
            foreach (var error in result.Errors) 
            { 
                SetError(error.PropertyName, error.ErrorMessage); 
  
                FirstNameHasError = true; 
                LastNameHasError = true; 
            } 
  
            if (result.IsValid) 
            { 
                FirstNameHasError = false; 
                LastNameHasError = false; 
                MessageBox.Show("Data good to save !"); 
            } 
  
        } 

Please have a modified sample from the below link
https://www.syncfusion.com/downloads/support/directtrac/general/ze/ModifiedSample882628976

Please refer below UG link for HasError and ErrorText properties mode details.
https://help.syncfusion.com/wpf/textinputlayout/assistive-labels#error-message

Let us know if you need any further assistance.

Regards,
Sridevi S.
 
 


Marked as answer

DJ Dhairya Joshi May 28, 2021 12:27 PM UTC

Hello Sridevi,

Thank you for response, 

I validated your way to handle HasError property by creating bool property for each and every Model property, I think that is not proper way to have it validated by having a clone bool property just to get validated.

Also I think I need to find a way to expose the HasError property of base class to my viewModel so that I can bind it to SfTextInputLayout.

Your solution will work fine but its lengthy. 

Out of the context if you have any suggestion to expose HasError property from BaseClass to VM, please do share or if this thread goes out of your SLR you can close it.

Appreciate your help and your solution.

Thank you,
Dhairya Joshi




DJ Dhairya Joshi May 29, 2021 04:54 PM UTC

Hello Sridevi,

I was able to figure out the solution.

I kept the base validation class as it is.

I played with HasError and ErrorText property to get what they want from ViewModel. It fixed the issue.

Validation is getting triggered.

Thank you,
Dhairya Joshi


SS Sridevi Sivakumar Syncfusion Team May 31, 2021 08:27 AM UTC

Hi Dhairya Joshi,

We are glad that you have found the solution, please let us know if you need any other assistance.

Regards,
Sridevi S. 



IO Ismail Ouadghiri El Idrissi October 8, 2021 03:34 PM UTC

Hi Dhairya Joshi,


Here is my solution for your problem, but instead of implementing INotifyDataErrorInfo I used 

IDataErrorInfo.


[XAML]

<syncfusion:SfTextInputLayout

                Grid.Row="0"

                Hint="Name"

                HelperText="Enter brand name"

                Margin="0,0,0,10"

                HasError="{Binding HasErrorCollection[Name]}"

                ErrorText="{Binding ErrorCollection[Name]}">

                <TextBox

                    Text="{Binding Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"

                    VerticalAlignment="Center"

                    VerticalContentAlignment="Center" />

            </syncfusion:SfTextInputLayout>



[C# | CreateBrandViewModelValidator]

public class CreateBrandViewModelValidator : AbstractValidator<CreateBrandViewModel>

    {

        public CreateBrandViewModelValidator()

        {

            RuleFor(p => p.Name)

                .NotEmpty()

                .MinimumLength(10);


            RuleFor(p => p.Description)

                .NotEmpty();

        }

    }



[C# | CreateBrandViewModel]

   

    public class CreateBrandViewModel : BaseScreenViewModel, IDataErrorInfo

    {

        private readonly CreateBrandViewModelValidator _validator;


        private string _name;

        private string _description;


        private Dictionary<string, string> _errorCollection = new Dictionary<string, string>();

        private Dictionary<string, bool> _hasErrorCollection = new Dictionary<string, bool>();


        public CreateBrandViewModel()

        {

            _validator = new CreateBrandViewModelValidator();

        }


        public string Name

        {

            get => _name;

            set

            {

                if (value != _name)

                {

                    _name = value;

                    NotifyOfPropertyChange(() => Name);

                    NotifyOfPropertyChange(() => CanCreate);

                }

            }

        }


        public string Description

        {

            get => _description;

            set

            {

                if (value != _description)

                {

                    _description = value;

                    NotifyOfPropertyChange(() => Description);

                    NotifyOfPropertyChange(() => CanCreate);

                }

            }

        }


        public Dictionary<string, string> ErrorCollection

        {

            get => _errorCollection;

            set

            {

                if (value != _errorCollection)

                {

                    _errorCollection = value;

                    NotifyOfPropertyChange(() => ErrorCollection);

                }

            }

        }


        public Dictionary<string, bool> HasErrorCollection

        {

            get => _hasErrorCollection;

            set

            {

                if (value != _hasErrorCollection)

                {

                    _hasErrorCollection = value;

                    NotifyOfPropertyChange(() => HasErrorCollection);

                }

            }

        }


        public string Error => null;


        public string this[string columnName]

        {

            get

            {

                var validation = _validator.Validate(this, options =>

                {

                    options.IncludeProperties(columnName);

                });


                if (!validation.IsValid)

                {

                    var failures = validation.Errors;


                    var error = failures

                        .Where(p => p.PropertyName == columnName)

                        .Select(e => e.ErrorMessage)

                        .First();


                    if (!ErrorCollection.ContainsKey(columnName))

                        ErrorCollection.Add(columnName, null);


                    if (!HasErrorCollection.ContainsKey(columnName))

                        HasErrorCollection.Add(columnName, false);


                    ErrorCollection[columnName] = error;

                    HasErrorCollection[columnName] = true;


                    NotifyOfPropertyChange(() => ErrorCollection);

                    NotifyOfPropertyChange(() => HasErrorCollection);


                    return error;

                }

                else

                {

                    ErrorCollection[columnName] = null;

                    HasErrorCollection[columnName] = false;

                    NotifyOfPropertyChange(() => HasErrorCollection);

                    NotifyOfPropertyChange(() => ErrorCollection);

                }


                return null;

            }

        }

    }



VR Vignesh Ramesh Syncfusion Team October 11, 2021 11:32 AM UTC

Hi Ismail Ouadghiri, 

Thanks for sharing solution with us. Please get in touch with us if you would require any further assistance.  

Regards, 
Vignesh Ramesh. 


Loader.
Up arrow icon