How it work with Error provider?

Feb 12, 2010 at 8:31 AM

HI,

Firstly, i really exciting about SpecExpress.

I just have a question. Does SpecExpress support error provider in WinForm client,

if does could you please show me how to use it?

Thanks!

Coordinator
Feb 12, 2010 at 9:44 PM

I am glad to hear your excited about SpecExpress and hope you find it very useful in your projects!

We are currently working to expand our examples of various UI examples.  As you know there are quite a few options out there (WinForms, WPF, Silverlight, ASP.Net, ASP.NET MVC, etc), and certainly our goal is to provide a good example for each.  Although we currently do not have an example for WinForms, does not mean we can't help give you some guidance though!

It seems that when it comes to WinForms, if you are binding controls through an ObjectDatasource, you can leverage an ErrorProvider control to display input errors for each bound control.  For a simple, well stated example see http://www.codegod.de/WebAppCodeGod/objectdatasource-and-idataerrorinfo-with-winforms-AID427.aspx.  Using this approach the goal would be to simply leverage SpecExpress in the implementation of IDataErrorInfo.

Perhaps "simply" is an understatement though.  There are two issues we would need to address:
                1) When to validate the object, and
                2) How to aggregate the resulting ValidationNotification messages in a format that is readable by the user.

As for number 1, the ValidationCatalog has an override to the Validate method that allows us to validate a specific property that seems to be perfect since the IDataErrorInfo interface demands that we return the validation state for a given property through the Item indexer.

So perhaps the IDataErrorInfo implementation might look something like this:

private string _lastError = "";

public string Error
{
	get { return _lastError; }
}

public string this[string columnName]
{
	get
	{
		var notification = ValidationCatalog.Validate(this,columnName);
        if (notification.IsValid)
        {
			_lastError = string.empty;
        }
        else
        {
			// Todo: aggregate notification messages in readable form and assign to _lastError
        }

        return _lastError;
    }
}

The ValidationNotification models a hierarchy of errors that model the same hierarchy of the object / property that was validated.  It does this through a list of a list of Errors and each Error may reference another ValidationResult (through the NestedResult property).  There are numerous ways to model this hierarchy in the UI, but in this situation, we are limited to a single string error message.  This means that we must have someway of walking the hierarchy to obtain the error message.  One way to accomplish this is to create an extension method to the ValidationNotification class like this:

 

public static class ValidationNotificationExtentions
{
    public static List<string> ErrorSummary(this ValidationNotification notification)
    {
        return GetAllResultMessages(notification.Errors, string.Empty);
    }

    private static List<string> GetAllResultMessages(IEnumerable<ValidationResult> results, string prefix)
    {
        List<string> messages = new List<string>();
        foreach (ValidationResult result in results)
        {
			if (result.NestedValdiationResults != null && result.NestedValdiationResults.Count() > 0)
            {
                messages.AddRange(GetAllResultMessages(result.NestedValdiationResults, ApplyPrefix(prefix, result.Property.Name.SplitPascalCase())));
            }
            else
            {
                messages.Add(ApplyPrefix(prefix, result.Message));
            }
        }

        return messages;
    }

    private static string ApplyPrefix(string prefix, string target)
    {
        if (string.IsNullOrEmpty(prefix))
        {
            return target;
        }
        else
        {
            return prefix + " " + target;
        }
    }
}

So then, the finished IDataErrorInfo implementation would look like this:

private string _lastError = "";

public string Error
{
	get { return _lastError; }
}

public string this[string columnName]
{
	get
	{
		var notification = ValidationCatalog.Validate(this,columnName);
        if (notification.IsValid)
        {
		_lastError = string.empty;
        }
        else
        {
		_lastError = notification.ErrorSummary();
        }

        return _lastError;
    }
}

This, of course is one of many approaches and may or may not be best suited for your solution, but it should get you thinking!  Also, the above samples come with the WIMM guarantee (Works in my mind).

Feb 28, 2010 at 3:27 PM

Sorry for replying you so late cause i'm on vacation!

I've already implemented SpecExpress as Validation for my project sucessfully that based on your sugestion. And it is very convenience.

I also wrote a blog in vietnamese how to Implement with error provider here.

By the way, i just wonder how to localize error message in SpecExpress? I think this project is very usefull and i want to localize messeage in Vietnamese, so that we can use it directly.

Thanks.

 

Coordinator
Feb 28, 2010 at 7:04 PM

Thanks for the feedback. 

I created some documentation for localizing error messages at http://specexpress.codeplex.com/wikipage?title=Localization. Make sure and send us a copy of the file and we'll commit it so it'll be available in the next release. Please let us know if you have any questions or issues with the localization.

Thanks,

Alan