3

I have implemented a PropertyGrid and properties of selected object(in another library) are displayed in it. Property values are bound to PropertyGrid controls through binding. Now, I want to perform validation on values user enters in PropertyGrid control(mainly TextBox) and display a message to user if value is not correct.

There will be some common validations like numeric values, required field etc and some business logic related validations(like value can't be more then this etc.).

What all approaches are available to implement this(IDataErrorInfo or something else)?

akjoshi
  • 15,374
  • 13
  • 103
  • 121

3 Answers3

2

If you already have implemented IDataErrorInfo on your ViewModels, I found this data-template to be quite useful for displaying errors:

<Style TargetType="{x:Type TextBox}">
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="true">
            <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
        </Trigger>
    </Style.Triggers>
</Style>

That way, you only have to set ValidatesOnDataErrors=True on your textbox bindings and you get a tooltip displaying the error if anything is wrong. That can be applied to other controls as well.

For information on how to implement IDataErrorInfo properly, look here:
http://blogs.msdn.com/b/wpfsdk/archive/2007/10/02/data-validation-in-3-5.aspx
especially have a look at the section "3.5 IDataErrorInfo Support"

akjoshi
  • 15,374
  • 13
  • 103
  • 121
Botz3000
  • 39,020
  • 8
  • 103
  • 127
  • Thanks Botz, can you please provide me some code on how you have implemented IDataErrorInfo in your ViewModels. Actually in my case I have dependency properties in my controls(derived from UserControl), I need to validate these properties. – akjoshi Dec 09 '10 at 10:57
  • i have added a link where you can see how to implement it. – Botz3000 Dec 09 '10 at 12:10
  • I saw that article yesterday but I am confused about how to implement IDataErrorInfo with Inherited controls. I have a BaseControl (having some common dependency properties) and my controls are inherited from this base control and have some other dependency properties. I need to perform validations on all the dependency properties(parent + child). – akjoshi Dec 10 '10 at 05:41
  • I don't quite understand. You usually implement IDataErrorInfo on your ViewModels, i.e. the objects you bind your controls to. I don't think it should be implemented on the controls themselves. Your controls wouldn't even know what to validate, only your data objects know. – Botz3000 Dec 10 '10 at 08:21
  • Ya you may be right, but in my scenario we are not using MVVM. There are two libraries of custom controls, one having controls and one having PropertyGrid. Now, my custom controls have various dependency properties which are used by PropertyGrid to make them editable. – akjoshi Dec 10 '10 at 09:07
  • i see. Something like a forms designer? I guess you could check for the return value of base[field] in the indexer, and if that returns null or empty, return the derived indexer value. – Botz3000 Dec 10 '10 at 10:36
1

I recently had to deal with this problem so I will post this example code to help others with the same problem.

using System.Collections.Generic;
using System.ComponentModel;
using System.Text;

namespace ValidationExample
{

    public class SomeClass : DataErrorInfoImpl
    {
        [CustomValidation(typeof (SomeClassValidator), "ValidateSomeTextToValidate")]
        string SomeTextToValidate {get;set;}

    }

    public class SomeClassValidator
    {
        public static ValidationResult ValidateNumberOfLevelDivisons(string text)
        {
            if (text != "What every condition i want") return new ValidationResult("Text did not meet my condition.");
            return ValidationResult.Success;
        }

    }

    public class DataErrorInfoImpl : IDataErrorInfo
    {
        string IDataErrorInfo.Error { get { return string.Empty; } }

        string IDataErrorInfo.this[string columnName]
        {
            get
            {
                var pi = GetType().GetProperty(columnName);
                var value = pi.GetValue(this, null);

                var context = new ValidationContext(this, null, null) { MemberName = columnName };
                var validationResults = new List<ValidationResult>();
                if (!Validator.TryValidateProperty(value, context, validationResults))
                {
                    var sb = new StringBuilder();
                    foreach (var vr in validationResults)
                    {
                        sb.AppendLine(vr.ErrorMessage);
                    }
                    return sb.ToString().Trim();
                }
                return null;
            }
        }
    }
}

This style should work on WPF Xceed.PropertyGrid and WPF PropertyTools.PropertyGrid.

Greg
  • 1,549
  • 1
  • 20
  • 34
0

I recommend using IDataErrorInfo. That way, validation logic stays attached to ViewModel and not the UI. And WPF has well support for it as well.

decyclone
  • 30,394
  • 6
  • 63
  • 80