5

i am new to WPF, I am trying to Validate some WPF controls i have been following this link WPF Binding Validations

and i have understood how they are doing it. but what i want is to have a common textblock showing error messages for all the controls, in the above link they use a separate textblock for each of the controls to view the error message, but i want to just change the border color of the control to red in case of the error and show the error messages in a textblock which is created to view the error messages for any of the textboxes that has the false input. for example i have a textblock as

<TextBlock Name="txtError" Foreground="Red" Grid.ColumnSpan="3" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>

so whenever the text of any textboxes changes and validation rule returns false i want the border of that textbox red and the message to be displayed in the above textblock.

Muds
  • 4,006
  • 5
  • 31
  • 53
Abdullah Malikyar
  • 231
  • 1
  • 4
  • 19

4 Answers4

2

Welcome to world of bindings, you can solve this issue by just making some more text boxes with bindings (as suggested in prev. answer) and have a style to show problem text box as red.

But I would suggest you to understand the concept of DataValidation and DataErrorInfo in wpf, on a quick search I think This is a good starting point, read about it its worth your time.

After you understand data error info, you can set data error template on your textbox to work around the red border requirement.

Muds
  • 4,006
  • 5
  • 31
  • 53
1

It is much easier if you implement either the IDataErrorInfo Interface or the INotifyDataErrorInfo Interface in your data model class. The first interface provides a string Error property and the second a GetErrors method that returns a collection of errors. You can then data bind these properties to either a TextBlock or an ItemsControl to display all errors that relate to an object.

Not wanting to duplicate the many online examples, I prefer to direct you to them instead. You can find help with implementing these interfaces in the How to: Implement Validation Logic on Custom Objects and How to implement INotifyDataErrorInfo in WPF 4.5? posts online.

Note that although the IDataErrorInfo interface was designed to deal with individual errors, you can alter it to deal with multiple errors if you add an Errors collection property. Take this example:

public string Error
{
    get
    {
        StringBuilder errors = new StringBuilder();
        foreach (string error in Errors) errors.AppendUniqueOnNewLineIfNotEmpty(error);
        return errors.ToString();
    }
}

public override ObservableCollection<string> Errors
{
    get
    {
        errors = new ObservableCollection<string>();
        errors.AddUniqueIfNotEmpty(this["Property1"]);
        errors.AddUniqueIfNotEmpty(this["Property2"]);
        errors.AddUniqueIfNotEmpty(this["PropertyN"]);
        errors.AddRange(ExternalErrors);
        return errors;
    }
}

The AddUniqueIfNotEmpty method is just an extension helper method that I created which 'does what it says on the tin'.

Community
  • 1
  • 1
Sheridan
  • 68,826
  • 24
  • 143
  • 183
0

If You are using MVVM - just create public property caled errorMessage and bind it to this textbox:

private string _emailMessage;
public string emailMessage
{
    get
    {
        return _emailMessage;
    }
    set
    {
        _emailMessage = value;
        OnPropertyChanged(emailMessage);
    }

Now in xaml bind TextBlock.Text to this property:

<TextBlock Text="{Binding Path="emailMessage"}  .../>

If You are using code-behind instead of MVVM You can just set Textblock.Text each time error has occured. Like below:

If(somethingBadHappened)
{
    txtError.Text = "Some error text";
}
MajkeloDev
  • 1,661
  • 13
  • 30
0

Hello search engine visitor. You may be feeling underwhelmed by the other answers to this question. There are two correct answers, depending on exactly what you mean by "all errors":

All binding errors within the current control

If you have multiple bindings to properties which may produce binding validation errors, the correct way to gather them together is to add a BindingGroup to your control. You can then query this object for all of the errors produced by the bindings it knows of. I won't go into detail about how to set this up; check Microsoft's documentation.

All INotifyDataErrorInfo errors in the data object

Perhaps you don't actually have any bindings to individual properties, because (for example) you are displaying an error message in a prompt and need to list all of the reasons why the user can't proceed.

You can abuse the GetErrors method to return all known errors when a null/empty string is passed, but this is a hack. You could also add a new property which returns all errors, but this means changing your data model and adding bespoke handling for the errors changing.

I have a better solution for you: DataErrorsControl. This is a custom control which:

  1. Queries all properties of the ErrorSource object and flattens the resulting errors (with the help of CompositeCollection), then exposes that collection in read-only form as a CollectionView
  2. Has an IsExpanded property which determines whether it displays all of the errors as a list, or just one error at a time on a single line
  3. Supports asynchronous error generation, as required by the INotifyDataErrorInfo interface

Enjoy!

P.S. I also added support for navigating back/forward through the errors, but left the required buttons out of the default template to keep it simpler. You can add the UI or remove the command handlers per your requirements.

Artfunkel
  • 1,832
  • 17
  • 23