Powered by MSDN

US - English
NEW! Silverlight 5 is available Learn More

How to manually validate an object and have the results... RSS

16 replies

Last post May 23, 2012 12:43 PM by mtiede@swtechnologies.com

(0)
  • ryanhaney

    ryanhaney

    Member

    2 Points

    1 Post

    Re: How to manually validate an object and have the results automatically added to a ValidationSu...

    Dec 20, 2009 11:20 AM | LINK

    A little late, but figured this was a little more dynamic.

      

    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Media;
    
    public static class ValidationUtility
    {
        public static void Validate(object entity, UIElement element)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
            {
                var child = (UIElement)VisualTreeHelper.GetChild(element, i);
                Validate(entity, child);
            }
    
            if (element is FrameworkElement)
            {
                IEnumerable <bindingExpressions> = from f in element.GetType().GetFields(BindingFlags.Static | BindingFlags.Public)
                                                                    where f.FieldType == typeof(DependencyProperty)
                                                                    let be = ((FrameworkElement)element).GetBindingExpression ((DependencyProperty)f.GetValue(element))
                                                                    where be != null && be.ParentBinding != null && be.ParentBinding.ValidatesOnExceptions && be.DataItem == entity
                                                                    select be;
    
                foreach (BindingExpression bindingExpression in bindingExpressions)
                {
                    bindingExpression.UpdateSource();
                }
            }
        }
    }
     

  • billvo

    billvo

    Member

    6 Points

    4 Posts

    Re: Re: How to manually validate an object and have the results automatically added to a Validati...

    Jan 15, 2010 08:19 PM | LINK

    Cheers to ryanhaney for a sweet piece of LINQ code.  For those needing a VB translation, try this.  Note: This website doesn't like "GetBindingExpression"--so I've added a space below.

     

    Imports System.Linq
    Imports System.Reflection
    Imports System.Windows.Data
    
    Public Module ValidationUtility
    
        Public Sub Validate(ByVal entity As Object, ByVal element As UIElement)
            For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(element) - 1
                Dim child = DirectCast(VisualTreeHelper.GetChild(element, i), UIElement)
                Validate(entity, child)
            Next
    
            If TypeOf element Is FrameworkElement Then
                  Dim bindingExpressions = _
                    From bx In _
                        (From fd In element.GetType().GetFields(BindingFlags.Static Or BindingFlags.Public) _
                        Where fd.FieldType Is GetType(DependencyProperty) _
                        Select CType(element, FrameworkElement).GetBindingExpressio n(CType(fd.GetValue(element), DependencyProperty))) _
                    Where bx IsNot Nothing _
                    AndAlso bx.ParentBinding IsNot Nothing _
                    AndAlso bx.ParentBinding.ValidatesOnExceptions _
                    AndAlso Equals(bx.DataItem, entity) _
                    Select bx
    
                For Each bindingExpression As BindingExpression In bindingExpressions
                    bindingExpression.UpdateSource()
                Next
            End If
        End Sub
    End Module
     
  • vinco

    vinco

    Member

    4 Points

    2 Posts

    Re: How to manually validate an object and have the results automatically added to a ValidationSu...

    Jan 22, 2010 08:10 PM | LINK

    One more fix, ensures that all controls are already loaded. 

    public void ForceValidate(object entity, UIElement element)
            {
                Deployment.Current.Dispatcher.BeginInvoke(delegate()
                {
                    this.Validate(entity, element);
                });
            }
     

  • Kellen

    Kellen

    Member

    6 Points

    12 Posts

    Re: How to manually validate an object and have the results automatically added to a ValidationSu...

    Jul 22, 2010 06:40 PM | LINK

        public void ForceValidate(UIElement element)
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
                {
                    var child = (UIElement)VisualTreeHelper.GetChild(element, i);
                    ForceValidate(child);
                }
                if (element is FrameworkElement  && element.Visibility == Visibility.Visible)
                {
                    var type = element.GetType();
                    while (type != typeof(UIElement))
                    {
                        var bindingExpressions = from f in type.GetFields(BindingFlags.Static | BindingFlags.Public)
                                                 where f.FieldType == typeof(DependencyProperty)
                                                 let be = ((FrameworkElement)element).GetBindingExpression((DependencyProperty)f.GetValue(element))
                                                 where be != null && be.ParentBinding != null && be.ParentBinding.ValidatesOnExceptions && be.DataItem == this
                                                 select be;
                        foreach (BindingExpression bindingExpression in bindingExpressions)
                        {
                            bindingExpression.UpdateSource();
                        }
                        type = type.BaseType;
                    }
                }
            }

    Here's a bit of  tweak to the linq solution.  This will also pick up any bindings that are set using DependencyPropertys from a base class (ie SelectedItem for a dropdown).


            public void ForceValidate(UIElement element)
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
                {
                    var child = (UIElement)VisualTreeHelper.GetChild(element, i);
                    ForceValidate(child);
                }
    
                if (element is FrameworkElement  && element.Visibility == Visibility.Visible)
                {
                    var type = element.GetType();
                    while (type != typeof(UIElement))
                    {
                        var bindingExpressions = from f in type.GetFields(BindingFlags.Static | BindingFlags.Public)
                                                 where f.FieldType == typeof(DependencyProperty)
                                                 let be = ((FrameworkElement)element).GetBindingExpression((DependencyProperty)f.GetValue(element))
                                                 where be != null && be.ParentBinding != null && be.ParentBinding.ValidatesOnExceptions && be.DataItem == this
                                                 select be;
    
                        foreach (BindingExpression bindingExpression in bindingExpressions)
                        {
                            bindingExpression.UpdateSource();
                        }
                        type = type.BaseType;
                    }
                }
            }


  • jmix90

    jmix90

    Member

    12 Points

    8 Posts

    Re: How to manually validate an object and have the results automatically added to a ValidationSu...

    Oct 25, 2010 08:43 AM | LINK

    Hello,


    I personnaly use this solution : http://blog.lexique-du-net.com/index.php?post/2010/10/19/RIA-Services-Force-validation-on-my-entities-%28and-just-the-validation-%21%29


    ++ 

    Jonathan ANTOINE
    MVP - Client Application Development
    http://blog.lexique-du-net.com
    http://wpf-france.fr
  • sunil_ssb

    sunil_ssb

    Member

    4 Points

    3 Posts

    Re: How to manually validate an object and have the results automatically added to a ValidationSu...

    May 22, 2012 09:40 PM | LINK

    I am getting problem with Entity.HasValidationErrors flag. Custom Validation doesn't remove Errors from Entity. I am using ForceValidation method to validate my controls.
    Error raised by custom validator doesn't get removed from entity after fixing form values.
    I debugged custom validator on client side it doesn't raise any error once form value is fixed.

        public static void ForceValidation(IEnumerable uiElements)
            {
                foreach (var uiElement in uiElements)
                {
                    BindingExpression bindingExpression = null;

                    switch (uiElement.GetType().ToString())
                    {
                        case "System.Windows.Controls.StackPanel":
                        case "System.Windows.Controls.Panel":
                            ForceValidation(((Panel)uiElement).Children);
                            break;

                        case "System.Windows.Controls.TextBox":
                            bindingExpression = ((TextBox)uiElement).GetBindingExpression(TextBox.TextProperty);
                            break;

                        case "System.Windows.Controls":
                            bindingExpression = ((TextBox)uiElement).GetBindingExpression(TextBox.TextProperty);
                            break;

                        case "System.Windows.Controls.RadioButton":
                            bindingExpression = ((RadioButton)uiElement).GetBindingExpression(ToggleButton.IsCheckedProperty);
                            break;

                        case "Telerik.Windows.Controls.RadDatePicker":
                            bindingExpression = ((RadDatePicker)uiElement).GetBindingExpression(RadDatePicker.SelectedValueProperty);
                            break;

                        case "Telerik.Windows.Controls.RadMaskedTextBox":
                            bindingExpression = ((RadMaskedTextBox)uiElement).GetBindingExpression(RadMaskedTextBox.ValueProperty);
                            break;
                    }

                    if (bindingExpression == null || bindingExpression.ParentBinding == null) continue;
                    if (!bindingExpression.ParentBinding.ValidatesOnExceptions) continue;

                    bindingExpression.UpdateSource();
                }
            }






        public class CustomValidation
        {

            

            public static ValidationResult BizNo(string str)
            {
              

                // Perform validation logic here and set isValid to true or false.

                if(str.Equals("0000"))
                {
                    return new ValidationResult("Please enter valid biz no");
                }
                else
                {

                  return  ValidationResult.Success;
                }
            }
        }



            //This is how I am doing binding
              b = new Binding("ORequest.Customer_BIS_Number");
               b.Source = _oViewModel;
               b.Mode = BindingMode.TwoWay;
               b.NotifyOnValidationError = true;
               b.ValidatesOnExceptions = true;
               txtCusBizNo.SetBinding(TextBox.TextProperty, b);

            
               //This is how RIA service code generated looks at client side [CustomValidation(typeof(Bnz.Bi.DailySalesAndReferrals.Web.Shared.CustomValidation), "BizNo")]
            [DataMember()]
            [Required(ErrorMessage="Customer BIS Number is required.")]
            [StringLength(100)]
            public string Customer_BIS_Number
            {
                get
                {
                    return this._customer_BIS_Number;
                }
                set
                {
                    if ((this._customer_BIS_Number != value))
                    {
                        this.OnCustomer_BIS_NumberChanging(value);
                        this.RaiseDataMemberChanging("Customer_BIS_Number");
                        this.ValidateProperty("Customer_BIS_Number", value);
                        this._customer_BIS_Number = value;
                        this.RaiseDataMemberChanged("Customer_BIS_Number");
                        this.OnCustomer_BIS_NumberChanged();
                    }
                }
            }
        
             OnSave(){

             //This is how I call forcevalidation on My Silverlight ViewPage
             Helpers.Helper.ForceValidation(this.LayoutRoot.Children);
             
             //This flag is always true once custom validator finds any error
             //even after correcting form values
             ViewModel.MyEntity.HasValidationErrors;   }





             

  • mtiede@swtechnologies.com

    mtiede@swtec...

    Contributor

    5366 Points

    2236 Posts

    Re: How to manually validate an object and have the results automatically added to a ValidationSu...

    May 23, 2012 12:43 PM | LINK

    I'm guesssing you could just clear ALL the errors and then run the validator again.  (I don't use the Entity stuff so I'm not sure how you accomplish that)

    I haven't looked at this stuff for quite a while, but my recollection was that the tab controls don't show up until they are actually visible and I had to programmatically select each tab, iterate for errors, then reselect original tab.

    It MIGHT have been I had to do that so that the ValidationSummary actually had objects associated with the lines in the Summary.

    OR

    Maybe I had to iterate those to FIND the object in error.  So that when they clicked on the validation error it could locate the object in error for the user to see.  Otherwise, if the control in error was visible, clicking found and highlighted it and if it wasn't visible, it did nothing which would be confusing for the user.