Validation not working on Add Customer

Jul 27, 2011 at 3:46 PM

Hi Tony,

When you open pop up window on click Add button then validation is not working and button can not be disabled.

Its working fine for edit screen( when you change something on pop up screen then OK button is disabled)

Example: I have one scenario, On click Add new customer button, I have show pop up window here customer name is mandatory field but the validation it not show around text box & OK button is enabled & when i click it show error.(On entity level Customer name is mandatory field)

So How I can show on validation on Add Screen & the ok button is disabled please reply as soon as possible?.


Also If you have any screen cast on Validation topic in Simple MVVM RIA Service(Except entity-level and async validation, webinar on WCF RIA Services.)

 

I can not find the SimpleMvvm-RiaValidation sample application?

Jul 27, 2011 at 10:09 PM

Hi

I'm working on validation right now so thought I'd try and help. The samples are in SimpleMvvm-Samples.zip which on my install is in C:\Program Files (x86)\SimpleMvvmToolkit\Samples (that's Win 7 64-bit so will be C:\Program Files\SimpleMvvmToolkit\Samples if you are 32-bit). I have the SimpleMvvm-RiaValidation sample app open right now and I'm pretty sure it will have everything you need. In particular I think you need to call BeginEdit on the VM so that the OK button is disabled (if that;s how your logic is working) when the pop-up is shown.

Cheers - Graham

Jul 27, 2011 at 11:38 PM
Edited Jul 27, 2011 at 11:53 PM

Hi

its the same problem with SimpleMvvm-RiaValidation sample application as nrsonawane explained ( the Ok button in Add scenario never gets actived  while it works fine with edit scenario), i guess its with IsDirty property, which never get changed in Add scenario.

fix: call detailModel.BeginEdit() in addItemButton event handler (similar way as in editItemButton event handler).

Coordinator
Jul 28, 2011 at 4:28 PM
I'll take a look at this when I get a chance.

Cheers,
Tony
Sent from my iPhone

On Jul 27, 2011, at 6:38 PM, "sunilmunikar"<notifications@codeplex.com> wrote:

From: sunilmunikar

Hi

its the same problem with SimpleMvvm-RiaValidation sample application as nrsonawane explained ( the Ok button in Add scenario never gets actived while it works fine with edit scenario), i guess its with IsDirty property, which never get changed in Add scenario.

Aug 4, 2011 at 9:59 PM

Hi Tony

I've been working on validation recently using your SimpleMvvm-RiaValidation as a reference. As sunilmunikar says, to get the example working when adding a new item BeginEdit() needs to be called after creating the detailModel.

However, I think there is another problem which is that IsValid is true when the popup displays, when it should be false because the Name field is blank. Furthermore, in my application where there are several fields that have validation rules, IsValid is returning true even when there are fields that are invalid. This is always when these fields have not been 'touched' - as soon as they have been touched IsValid works as expected. I can get IsValid to work as I want by programatically touching each field after calling BeginEdit(), which has the side effect of showing the page with the red validation display around each invalid field. I think I quite like this, but I'm keen to get your thougts on how you think IsValid should work. I had assumed that after calling BeginEdit() each data property of the entity would be interrogated to find out if it was valid and IsValid would reflect the overall staus of the entity.

Here's hoping I haven't missed something obvious :)

Cheers - Graham

Coordinator
Aug 14, 2011 at 9:32 PM
Edited Aug 14, 2011 at 9:55 PM

Graham brings up an excellent point, which is that validation in WCF RIA Services only takes place when setting a property value on an entity.  Therefore, a new entity is considered to be "valid" because no property values have been set. This is most likely by design, because validation tests an incoming value against some rules *before* the value is actually set.  If the value does not pass muster, the entity is not placed in an invalid state. However, there are times when it would be nice to see if an entity is currently in a valid state. Unfortunately, the ValidateProperty method on an Entity-derived class in RIA Services is marked as protected, which means you cannot call it externally.

One way to address this is with a "partial" class, which becomes part of the generated entity class when the client project compiled.  You can create a partial class that adds a public ValidateProperty method, which calls the protected ValidateProperty method. Then in the ctor of the ViewModel you can call ValidateProperty!  Here is the Item partial class that I added to the project.

using System;
using System.Reflection;
using System.Linq;
using System.Linq.Expressions;
using System.ServiceModel.DomainServices.Client;

namespace SimpleMvvmRiaValidation.Web
{
    public sealed partial class Item : Entity
    {
        /// <summary>
        /// Allows you to specify a lambda for property validation
        /// </summary>
        /// <typeparam name="TResult">Property type</typeparam>
        /// <param name="property">Property for validation</param>
        /// <param name="value">Value being validated</param>
        public void ValidateProperty<TResult>
            (Expression<Func<Item, TResult>> property, object value)
        {
            // Convert expression to a property name
            string propertyName = ((MemberExpression)property.Body).Member.Name;

            // Validate property
            ValidateProperty(propertyName, value);
        }

        /// <summary>
        /// Allows you to specify a lambda for property validation
        /// </summary>
        /// <typeparam name="TResult">Property type</typeparam>
        /// <param name="property">Property for validation</param>
        public void ValidateProperty<TResult>
            (Expression<Func<Item, TResult>> property)
        {
            // Convert expression to a property name
            string propertyName = ((MemberExpression)property.Body).Member.Name;

            // Get current value of the property
            var prop = this.GetType().GetProperty(propertyName);
            object value = prop.GetValue(this, null);

            // Validate property
            ValidateProperty(propertyName, value);
        }

        /// <summary>
        /// Validate specific properties on the entity
        /// </summary>
        public void ValidateProperties(params string[] propertyNames)
        {
            // Iterate properties
            foreach (var prop in this.GetType().GetProperties())
            {
                if (propertyNames.Contains(prop.Name))
                {
                    // Get current value of the property
                    object value = prop.GetValue(this, null);

                    // Validate property
                    ValidateProperty(prop.Name, value);
                }
            }
        }
    }
}

Here is the modified version of the ItemDetailViewModel constructor.

public ItemDetailViewModel(Item model)
{
    base.Model = model;

    // Refresh CanSave on PropertyChanged
    if (base.Model.EntityState == EntityState.New
        || base.Model.EntityState == EntityState.Detached)
    {
        base.Model.ValidateProperty(m => m.Id);
        base.Model.ValidateProperty(m => m.Name);
    }
}

Lastly, there is one more glitch: ValidateProperty won't work if the initial value is null, so you have to set the Name to an empty string in the ctor of the ItemDetailViewModel.

public ItemDetailView(ItemDetailViewModel viewModel)
    : this()
{
    // HACK: Needed to validate on Add
    viewModel.Model.Name = string.Empty;

    // Set data context to view model
    DataContext = viewModel;
}

Here is a link to the modified SimpleMvvm-RiaValidation sample project. If you run it you'll see that validation works for Add as well as Edit. Enjoy.

Tony

Aug 15, 2011 at 6:21 AM

Hi Tony,

I have tried the attached sample i.e (SimpleMvvm-RiaValidation).

the validation working fine for Add only.  When you click on Edit the Name value is not displayed. it should blank.

Because you have set

// HACK: Needed to validate on Add
viewModel.Model.Name = string.Empty;

So how you can set the value for Edit.

Aug 16, 2011 at 7:29 PM

Hi nrsonawane

I think the answer to your question might be something like:

             // HACK: Needed to validate on Add
            if (viewModel.Model.EntityState == EntityState.New)
            {
                viewModel.Model.Name = string.Empty;
            }

This still leaves the OK button disabled when the ChildWindow displays in edit mode because IsDirty is False, however that is probably what is required in most scenarios.

Cheers - Graham

Coordinator
Aug 17, 2011 at 12:29 PM
Thanks Graham for your response -- been a busy week for me.

Cheers,
Tony
Aug 17, 2011 at 5:02 PM

Hi GrahamDSmith,

Now Ok button is disabled, but one more thing its does not show red rounded corner for Add scenario.

Thanks & Regards,

Nitin Sonawane

Aug 18, 2011 at 10:00 PM

Hi All

Looks like my earlier response wan't quite right, since in my (hurried) tests the EntityState always seems to be Detached and I haven't found a point to trap when it is new.

However, I hope you don't mind me saying so Tony but I do wonder but I do wonder if this is all geetting a bit too complex? In my app I can get validation to fire without the partial class by setting the properties of my entity, which is pretty much what has to happen by ensuring that properites aren't null (as in viewModel.Model.Name = string.Empty). What is a bit puzzling though is that in my app I can't get IsDirty to change to true without calling BeginEdit, whereas in the sample it does change to true.

Anyone else any thoughts on this?

Cheers - Graham

Sep 13, 2011 at 4:20 AM

Hey Graham and/or Tony;

  Has there been any progress on this topic?

 

Thanks for any info

Robert

Mar 22, 2012 at 6:45 PM
Edited Mar 22, 2012 at 6:52 PM

Hey guys, 

I know this is an old thread but I wanted to jump in and say I found a solution that works great for me. On the DetailsViewModel try calling the following code to force validation of the entity before you show the modal dialog and after your call to BeginEdit().

 

        public void ForceValidation()
        {
            var validationResults = new List<ValidationResult>();
            var validationContext = new ValidationContext(Model, null, null);
            Validator.TryValidateObject(Model, validationContext, validationResults);
            Model.ValidationErrors.Clear();
            foreach (var error in validationResults)
                Model.ValidationErrors.Add(error);
        }

Hope this helps. Credit is from this blog: http://www.michelsalib.com/2011/03/force-validation-of-ria-entities/

May 13, 2012 at 2:36 AM
Edited May 13, 2012 at 2:39 AM

Hey guys,

Yes this stuff is old but it is helpful indeed.
So just to continue with Graham regarding the Add hack, the EntityState will not equal EntityState.New so it will not fall through the viewModel.Model.Name = string.Empty;
Instead, if you're following the example by Tony, you probably have an Id property in the Model and it will be 0 when adding.

So using... 

If viewModel.Id = 0
{
	viewModel.Model.Name = string.Empty;
}

 will do the trick.

Thanks,
Jun

May 13, 2012 at 2:42 AM
Edited May 13, 2012 at 2:42 AM

Now for my issue... :)

Binding the OK button's IsEnabled to IsValid property of the Model will work just fine on Required properties (i.e., it will disable the button on blank entries).
But when the property is not in a valid format (e.g., entering non-numeric characters on a numeric property), the IsValid does not change.
Any thoughts on this?

Thanks,
Jun 

Jun 6, 2012 at 4:13 AM

I think you need the fourth (misnamed) valiateAllProperties bool parameter set to true on the TryValidateObject method.

Validator.TryValidateObject(Model, validationContext, validationResults, true);

Without it true, only Required validations are tested.

However the reason why I found this discussion is a further problem. While this does indeed raise errors visible on the View fields, they are not picked up by any ValidationSummary. While testing I can see the ValidationSummary momentarily display the errors during loading, but then it loses them.

Some other workarounds manually update the View controls, but it looks like they suffer from TabControl issues: http://forums.silverlight.net/t/111830.aspx/2/10