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);
}
}
}
}
}
}
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.................
Comments
Post a Comment