From d216f075a350a6960b353f0d232750dd0bc18208 Mon Sep 17 00:00:00 2001 From: Serge Pilipchuk <112853396+sergepilipchuk@users.noreply.github.com> Date: Thu, 18 Sep 2025 13:57:02 +0400 Subject: [PATCH 1/6] Update code (minor changes) --- CS/MainWindow.xaml | 3 +++ CS/MainWindow.xaml.cs | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CS/MainWindow.xaml b/CS/MainWindow.xaml index 4e1bb01..0e965ff 100644 --- a/CS/MainWindow.xaml +++ b/CS/MainWindow.xaml @@ -10,6 +10,9 @@ + + + diff --git a/CS/MainWindow.xaml.cs b/CS/MainWindow.xaml.cs index c13cca5..21aad52 100644 --- a/CS/MainWindow.xaml.cs +++ b/CS/MainWindow.xaml.cs @@ -51,15 +51,17 @@ void RaisePropertyChanged(string property) { string IDataErrorInfo.Error { get { return GetError(); } } + string GetError() { if (string.IsNullOrEmpty(TestString)) - return "ErrorType=Critical;ErrorContent=empty"; + return "ErrorType=Critical;ErrorContent=The value is not provided. Please enter a value"; if (TestString.Length < 3) - return "ErrorType=Critical;ErrorContent=error"; + return "ErrorType=Warning;ErrorContent=The value is less than 3 characters. Please enter at least 5 characters"; if (TestString.Length < 5) - return "ErrorType=Information;ErrorContent=warning"; + return "ErrorType=Information;ErrorContent=The value is less than 5 characters. Please enter at least 5 characters"; return string.Empty; } + string IDataErrorInfo.this[string columnName] { get { if (columnName == "TestString") From e0f77554ed1a17a96702d932fc177b6d6b5b3f97 Mon Sep 17 00:00:00 2001 From: Serge Pilipchuk <112853396+sergepilipchuk@users.noreply.github.com> Date: Thu, 18 Sep 2025 14:21:43 +0400 Subject: [PATCH 2/6] Update readme file (new template) --- Readme.md | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/Readme.md b/Readme.md index 368efed..9b5e47b 100644 --- a/Readme.md +++ b/Readme.md @@ -4,25 +4,38 @@ [![](https://img.shields.io/badge/📖_How_to_use_DevExpress_Examples-e9f6fc?style=flat-square)](https://docs.devexpress.com/GeneralInformation/403183) [![](https://img.shields.io/badge/💬_Leave_Feedback-feecdd?style=flat-square)](#does-this-example-address-your-development-requirementsobjectives) - -*Files to look at*: + +# WPF Editors - Indicate Errors and Warnings by Implementing IDataErrorInfo + +Please implement the `IDataErrorInfo` interface on the data object. Then, pass the text and type of error in the `IDataErrorInfo.Error` property ( it is possible to easily parse this string). Implement a custom style for the `ErrorControl`. This element presents the error icon. Modify the `ErrorControl` style in such a way as to take into account a custom error type and text (use the converter). + +## Implementation Details + +... + +## Files to Review * [MainWindow.xaml](./CS/MainWindow.xaml) (VB: [MainWindow.xaml](./VB/MainWindow.xaml)) * [MainWindow.xaml.cs](./CS/MainWindow.xaml.cs) (VB: [MainWindow.xaml.vb](./VB/MainWindow.xaml.vb)) - -# WPF Editors - Indicate errors and warnings by implementing IDataErrorInfo +## Documentation -

Please implement the IDataErrorInfo interface on the data object. Then, pass the text and type of error in the IDataErrorInfo.Error property ( it is possible to easily parse this string). Implement a custom style for the ErrorControl. This element presents the error icon. Modify the ErrorControl style in such a way as to take into account a custom error type and text (use the converter).


-

+* [TextEdit](https://docs.devexpress.com/WPF/DevExpress.Xpf.Editors.TextEdit) +* [EditValue](https://docs.devexpress.com/WPF/DevExpress.Xpf.Editors.BaseEdit.EditValue) +* [ErrorToolTipContentTemplate](https://docs.devexpress.com/WPF/DevExpress.Xpf.Editors.BaseEdit.ErrorToolTipContentTemplate) +* [ErrorContent](https://docs.devexpress.com/WPF/DevExpress.Xpf.Editors.Validation.BaseValidationError.ErrorContent) -
+## More Examples +* [WPF Data Editors - Create a Registration Form](https://github.com/DevExpress-Examples/wpf-data-editors-create-registration-form) +* [WPF Data Editors - Allow Users to Enter Only Positive Numbers](https://github.com/DevExpress-Examples/wpf-editors-prevent-negative-values) +* [WPF Data Grid - Use Custom Editors to Edit Cell Values](https://github.com/DevExpress-Examples/wpf-data-grid-use-custom-editors-to-edit-cell-values) +* [WPF Data Grid - How to Validate Cell Editors](https://github.com/DevExpress-Examples/wpf-data-grid-validate-cell-editors) -## Does this example address your development requirements/objectives? - -[](https://www.devexpress.com/support/examples/survey.xml?utm_source=github&utm_campaign=wpf-editors-validate-user-input-indicate-errors-idataerrorinfo&~~~was_helpful=yes) [](https://www.devexpress.com/support/examples/survey.xml?utm_source=github&utm_campaign=wpf-editors-validate-user-input-indicate-errors-idataerrorinfo&~~~was_helpful=no) - +## Does this example address your development requirements/objectives? + +[](https://www.devexpress.com/support/examples/survey.xml?utm_source=github&utm_campaign=wpf-editors-validate-user-input-indicate-errors-idataerrorinfo&~~~was_helpful=yes) [](https://www.devexpress.com/support/examples/survey.xml?utm_source=github&utm_campaign=wpf-editors-validate-user-input-indicate-errors-idataerrorinfo&~~~was_helpful=no) + (you will be redirected to DevExpress.com to submit your response) From 944f13c07331221140e41bd590d4a95664848eef Mon Sep 17 00:00:00 2001 From: Serge Pilipchuk <112853396+sergepilipchuk@users.noreply.github.com> Date: Thu, 18 Sep 2025 16:29:07 +0400 Subject: [PATCH 3/6] Update readme (Implementation details) --- Readme.md | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index 9b5e47b..046ec93 100644 --- a/Readme.md +++ b/Readme.md @@ -7,11 +7,74 @@ # WPF Editors - Indicate Errors and Warnings by Implementing IDataErrorInfo -Please implement the `IDataErrorInfo` interface on the data object. Then, pass the text and type of error in the `IDataErrorInfo.Error` property ( it is possible to easily parse this string). Implement a custom style for the `ErrorControl`. This element presents the error icon. Modify the `ErrorControl` style in such a way as to take into account a custom error type and text (use the converter). +This example validates the input field and displays error indicators in DevExpress editors. The solution implements the standard `IDataErrorInfo` interface and uses a custom `ErrorControl` style to display different icons and messages for errors, warnings, and informational notes. + +Users can see visual indicators (error, warning, information) directly in the editor. Each indicator includes a descriptive message that helps users quickly fix input mistakes. + +GIF ## Implementation Details -... +### Create Validation Logic + +The data object implements the `IDataErrorInfo` interface. The `Error` property returns a formatted string that includes the error type and message: + +```csharp +public class TestClass : IDataErrorInfo { + public string TestString { get; set; } + + string IDataErrorInfo.Error { + get { return GetError(); } + } + + string GetError() { + if (string.IsNullOrEmpty(TestString)) + return "ErrorType=Critical;ErrorContent=The value is not provided. Please enter a value"; + if (TestString.Length < 3) + return "ErrorType=Warning;ErrorContent=The value is less than 3 characters. Please enter at least 5 characters"; + if (TestString.Length < 5) + return "ErrorType=Information;ErrorContent=The value is less than 5 characters. Please enter at least 5 characters"; + return string.Empty; + } + + string IDataErrorInfo.this[string columnName] { + get { + if (columnName == "TestString") + return GetError(); + return string.Empty; + } + } +} +``` + +### Parse Error Content + +The error string encodes multiple values (`ErrorType` and `ErrorContent`). A value converter extracts the required part of the string that displays it in the UI: + +```csharp +public class ErrorContentConverter : IValueConverter { + public string GetValueTag { get; set; } + public string Separator { get; set; } + + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { + if (value == null || !(value is string)) + return value; + string error = System.Convert.ToString(value, culture); + if (string.IsNullOrEmpty(error)) + return value; + + string searchString = GetValueTag + "="; + foreach (string suberror in error.Split(new string[] { Separator }, StringSplitOptions.RemoveEmptyEntries)) { + if (suberror.Contains(searchString)) + return suberror.Replace(searchString, string.Empty); + } + return value; + } + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { + return null; + } +} +``` ## Files to Review From 877f16e48921a2b14fbebcd2119731018a268022 Mon Sep 17 00:00:00 2001 From: Serge Pilipchuk <112853396+sergepilipchuk@users.noreply.github.com> Date: Fri, 19 Sep 2025 10:19:22 +0400 Subject: [PATCH 4/6] Update readme file (minor changes) --- Images/validation.jpg | Bin 0 -> 23005 bytes Readme.md | 42 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 Images/validation.jpg diff --git a/Images/validation.jpg b/Images/validation.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9a38ef7c99aa0d11351f1a124fb1de3bdc04e9fa GIT binary patch literal 23005 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 wHdEpNUpF7YtEg3*9n0T#T=k + + + + + + + + + + + + + + + + + +``` + ## Files to Review * [MainWindow.xaml](./CS/MainWindow.xaml) (VB: [MainWindow.xaml](./VB/MainWindow.xaml)) From 32a97f99617985be8948500fdc3e4cc4598be4d6 Mon Sep 17 00:00:00 2001 From: Serge Pilipchuk <112853396+sergepilipchuk@users.noreply.github.com> Date: Fri, 19 Sep 2025 12:09:32 +0400 Subject: [PATCH 5/6] Add changes after review (fresh eye) --- Readme.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Readme.md b/Readme.md index e704698..5025827 100644 --- a/Readme.md +++ b/Readme.md @@ -7,9 +7,7 @@ # WPF Editors - Indicate Errors and Warnings by Implementing IDataErrorInfo -This example validates the input field and displays error indicators in DevExpress editors. The solution implements the standard `IDataErrorInfo` interface and uses a custom `ErrorControl` style to display different icons and messages for errors, warnings, and informational notes. - -Users can see visual indicators (error, warning, information) directly in the editor. Each indicator includes a descriptive message that helps users quickly fix input mistakes. +This example validates input in a WPF [`TextEdit`](https://docs.devexpress.com/WPF/DevExpress.Xpf.Editors.TextEdit) and displays a warning if validation fails. It implements the standard `IDataErrorInfo` interface and applies a custom `ErrorControl` style to display icons (error, warning, information) along with descriptive messages to help users quickly correct input errors. ![Indicate Errors and Warnings by Implementing IDataErrorInfo](./Images/validation.jpg) From 98561fb3e9cf5ce140df50123566a6b497f18c3a Mon Sep 17 00:00:00 2001 From: Serge Pilipchuk <112853396+sergepilipchuk@users.noreply.github.com> Date: Fri, 19 Sep 2025 14:53:04 +0400 Subject: [PATCH 6/6] Apply suggestions from code review Co-authored-by: dirkpieterse --- Readme.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index 5025827..1bc045d 100644 --- a/Readme.md +++ b/Readme.md @@ -7,7 +7,8 @@ # WPF Editors - Indicate Errors and Warnings by Implementing IDataErrorInfo -This example validates input in a WPF [`TextEdit`](https://docs.devexpress.com/WPF/DevExpress.Xpf.Editors.TextEdit) and displays a warning if validation fails. It implements the standard `IDataErrorInfo` interface and applies a custom `ErrorControl` style to display icons (error, warning, information) along with descriptive messages to help users quickly correct input errors. +This example validates input in a WPF [`TextEdit`](https://docs.devexpress.com/WPF/DevExpress.Xpf.Editors.TextEdit) and displays a warning if validation fails. It implements the standard `IDataErrorInfo` interface and applies a custom `ErrorControl` style to display icons (error, warning, information) along with descriptive messages to help users correct input errors. + ![Indicate Errors and Warnings by Implementing IDataErrorInfo](./Images/validation.jpg) @@ -47,7 +48,8 @@ public class TestClass : IDataErrorInfo { ### Parse Error Content -The error string encodes multiple values (`ErrorType` and `ErrorContent`). A value converter extracts the required part of the string that displays it in the UI: +The error string encodes multiple values (`ErrorType` and `ErrorContent`). A value converter extracts these parts and displays them in the UI: + ```csharp public class ErrorContentConverter : IValueConverter {