WPF Validator as ajax/ Jquery

You can use wpf validator more smooth as ajax/ jquery. Just complete the following with me.

 Step 1.

       Open A new Window in WPF

Step 2. Add a class Which will provide the Validation

          /************ StringAtikStringValidationRule ************/

using System.Globalization;
using System.Windows.Controls;

namespace WpfApplication4
{
    public class StringAtikStringValidationRule : ValidationRule
    {
        private int _minimumLength = -1;
        private int _maximumLength = -1;
        private string _errorMessage;

        public int MinimumLength
        {
            get { return _minimumLength; }
            set { _minimumLength = value; }
        }

        public int MaximumLength
        {
            get { return _maximumLength; }
            set { _maximumLength = value; }
        }

        public string ErrorMessage
        {
            get { return _errorMessage; }
            set { _errorMessage = value; }
        }

        public override ValidationResult Validate(object value,
            CultureInfo cultureInfo)
        {
            ValidationResult result = new ValidationResult(true, null);
            string inputString = (value ?? string.Empty).ToString();
            if (inputString == null)
            {
                inputString = string.Empty;
            }

            if (inputString.Length < this.MinimumLength ||
                   (this.MaximumLength > 0 &&
                    inputString.Length > this.MaximumLength))
            {
                result = new ValidationResult(false, this.ErrorMessage);
            }
            return result;
        }
    }
}
                  /********End Of the Class**********/

Step 3. Now add a class which will Show the Error Message

           /**************ErrorProvider ************/

using System.Collections.Generic;
using System.Windows.Controls;
using System.Windows;
using System.ComponentModel;
using System.Windows.Data;
using System.Reflection;

namespace WpfApplication4
{
    public class ErrorProvider : Decorator
    {
        private delegate void FoundBindingCallbackDelegate(FrameworkElement element, Binding binding, DependencyProperty dp);
        private FrameworkElement _firstInvalidElement;
        private Dictionary<DependencyObject, Style> _backupStyles = new Dictionary<DependencyObject, Style>();

        /// <summary>
        /// Constructor.
        /// </summary>
        public ErrorProvider()
        {
            this.DataContextChanged += new DependencyPropertyChangedEventHandler(ErrorProviderDataContextChanged);
            this.Loaded += new RoutedEventHandler(ErrorProviderLoaded);
        }

        /// <summary>
        /// Called when this component is loaded. We have a call to Validate here that way errors appear from the very
        /// moment the page or form is visible.
        /// </summary>
        private void ErrorProviderLoaded(object sender, RoutedEventArgs e)
        {
            Validate();
        }

        /// <summary>
        /// Called when our DataContext changes.
        /// </summary>
        private void ErrorProviderDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if (e.OldValue != null && e.OldValue is INotifyPropertyChanged)
            {
                ((INotifyPropertyChanged)e.NewValue).PropertyChanged -= new PropertyChangedEventHandler(DataContextPropertyChanged);
            }

            if (e.NewValue != null && e.NewValue is INotifyPropertyChanged)
            {
                ((INotifyPropertyChanged)e.NewValue).PropertyChanged += new PropertyChangedEventHandler(DataContextPropertyChanged);
            }

            Validate();
        }

        /// <summary>
        /// Validates all properties on the current data source.
        /// </summary>
        /// <returns>True if there are no errors displayed, otherwise false.</returns>
        /// <remarks>
        /// Note that only errors on properties that are displayed are included. Other errors, such as errors for properties that are not displayed,
        /// will not be validated by this method.
        /// </remarks>
        public bool Validate()
        {
            bool isValid = true;
            _firstInvalidElement = null;

            if (this.DataContext is IDataErrorInfo)
            {
                List<Binding> allKnownBindings = ClearInternal();

                // Now show all errors
                foreach (Binding knownBinding in allKnownBindings)
                {
                    string errorMessage = ((IDataErrorInfo)this.DataContext)[knownBinding.Path.Path];
                    if (errorMessage != null && errorMessage.Length > 0)
                    {
                        isValid = false;

                        // Display the error on any elements bound to the property
                        FindBindingsRecursively(
                        this.Parent,
                        delegate(FrameworkElement element, Binding binding, DependencyProperty dp)
                        {
                            if (knownBinding.Path.Path == binding.Path.Path)
                            {

                                BindingExpression expression = element.GetBindingExpression(dp);
                                ValidationError error = new ValidationError(new ExceptionValidationRule(), expression, errorMessage, null);
                                System.Windows.Controls.Validation.MarkInvalid(expression, error);

                                if (_firstInvalidElement == null)
                                {
                                    _firstInvalidElement = element;
                                }
                                return;

                            }
                        });
                    }
                }
            }
            return isValid;
        }

        /// <summary>
        /// Returns the first element that this error provider has labelled as invalid. This method
        /// is useful to set the users focus on the first visible error field on a page.
        /// </summary>
        /// <returns></returns>
        public FrameworkElement GetFirstInvalidElement()
        {
            return _firstInvalidElement;
        }

        /// <summary>
        /// Clears any error messages.
        /// </summary>
        public void Clear()
        {
            ClearInternal();
        }

        /// <summary>
        /// Clears any error messages and returns a list of all bindings on the current form/page. This is simply so
        /// it can be reused by the Validate method.
        /// </summary>
        /// <returns>A list of all known bindings.</returns>
        private List<Binding> ClearInternal()
        {
            // Clear all errors
            List<Binding> bindings = new List<Binding>();
            FindBindingsRecursively(
                    this.Parent,
                    delegate(FrameworkElement element, Binding binding, DependencyProperty dp)
                    {
                        // Remember this bound element. We'll use this to display error messages for each property.
                        bindings.Add(binding);
                    });
            return bindings;
        }

        /// <summary>
        /// Called when the PropertyChanged event is raised from the object we are bound to - that is, our data context.
        /// </summary>
        private void DataContextPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsValid")
            {
                return;
            }
            Validate();
        }

        /// <summary>
        /// Recursively goes through the control tree, looking for bindings on the current data context.
        /// </summary>
        /// <param name="element">The root element to start searching at.</param>
        /// <param name="callbackDelegate">A delegate called when a binding if found.</param>
        private void FindBindingsRecursively(DependencyObject element, FoundBindingCallbackDelegate callbackDelegate)
        {

            // See if we should display the errors on this element
            MemberInfo[] members = element.GetType().GetMembers(BindingFlags.Static |
                    BindingFlags.Public |
                    BindingFlags.FlattenHierarchy);

            foreach (MemberInfo member in members)
            {
                DependencyProperty dp = null;

                // Check to see if the field or property we were given is a dependency property
                if (member.MemberType == MemberTypes.Field)
                {
                    FieldInfo field = (FieldInfo)member;
                    if (typeof(DependencyProperty).IsAssignableFrom(field.FieldType))
                    {
                        dp = (DependencyProperty)field.GetValue(element);
                    }
                }
                else if (member.MemberType == MemberTypes.Property)
                {
                    PropertyInfo prop = (PropertyInfo)member;
                    if (typeof(DependencyProperty).IsAssignableFrom(prop.PropertyType))
                    {
                        dp = (DependencyProperty)prop.GetValue(element, null);
                    }
                }

                if (dp != null)
                {
                    // Awesome, we have a dependency property. does it have a binding? If yes, is it bound to the property we're interested in?
                    Binding bb = BindingOperations.GetBinding(element, dp);
                    if (bb != null)
                    {
                        // This element has a DependencyProperty that we know of that is bound to the property we're interested in.
                        // Now we just tell the callback and the caller will handle it.
                        if (element is FrameworkElement)
                        {
                            if (((FrameworkElement)element).DataContext == this.DataContext)
                            {
                                callbackDelegate((FrameworkElement)element, bb, dp);
                            }
                        }
                    }
                }
            }

            // Now, recurse through any child elements
            if (element is FrameworkElement || element is FrameworkContentElement)
            {
                foreach (object childElement in LogicalTreeHelper.GetChildren(element))
                {
                    if (childElement is DependencyObject)
                    {
                        FindBindingsRecursively((DependencyObject)childElement, callbackDelegate);
                    }
                }
            }
        }
    }
}
              /*********** End Of The Error Provider Class*************/

 Step.4 Now add the XAML code in App.xaml in application Resource Which will take effect On Every Page.

               /****************** App.XAML ********************/

  <Application.Resources>
        <Style TargetType="{x:Type TextBox}">
            <Setter Property="Validation.ErrorTemplate">
                <Setter.Value>
                    <ControlTemplate>
                        <DockPanel LastChildFill="True">

                            <TextBlock DockPanel.Dock="Right"
Foreground="Orange"
Margin="5" 
FontSize="12pt"
Text="{Binding ElementName=MyAdorner, 
                               Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
                            </TextBlock>

                            <Border BorderBrush="Green" BorderThickness="3">
                                <AdornedElementPlaceholder Name="MyAdorner" />
                            </Border>

                        </DockPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <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>
    </Application.Resources>

                              /****************End Of App XAML***************/

step 5. Now customise your UI Field which you want to set validate. Consider a text Box then xaml will be

                            /************* Text box xaml*************/
 <StackPanel>
            <TextBox Height="23" HorizontalAlignment="Left" Margin="93,91,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" >
                <TextBox.Text>
                    <Binding Path="Name" UpdateSourceTrigger="PropertyChanged">
                        <Binding.ValidationRules>
                            <local:StringAtikStringValidationRule MinimumLength="1" MaximumLength="30" 
ErrorMessage="Name is required." />
                        </Binding.ValidationRules>
                    </Binding>
                </TextBox.Text>
            </TextBox>
        </StackPanel>

                           /*********** End Of xaml Stack***************/
Step 6. create a class in which aspect you bind the text field consider customer class.

                          /************ Customer Class ************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WpfApplication4
{
    public class Customer
    {
        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }
    }
}
              /********** End Of Customer Class**********/
step 7. Now declare the class at the initially of your UI.
                      /***************** Initial in UI *****************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace WpfApplication4
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            Customer c = new Customer();

            InitializeComponent();
            this.DataContext = c;
        }
    }
}
                         /******************* End of initialization UI *********************/
Enjoy................. 


Popular posts from this blog

WPF Crystal Report Viewer Using SAP

ASP.NET MVC razor SAP Crystal report