Reputation: 365
I am trying learn how to implement data validation but my first attempt is not firing the lblSource_Error event; does anyone know what I have missed?
My Window's XAML:
<Window x:Class="cCompleteWPFResourcesExamples.wValidationRule"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:cCompleteWPFResourcesExamples"
Title="wValidationRule" Height="300" Width="300">
<Window.Resources>
<local:Customer x:Key="rCustomer" Forename="InXaml" Surname="Created" ID="1"
AmountOutstanding="0"/>
</Window.Resources>
<StackPanel x:Name="stkMain" DataContext="{StaticResource rCustomer}">
<Label x:Name="lblSource" Validation.Error="lblSource_Error">
<Label.Content>
<Binding Path="ID" NotifyOnValidationError="True">
<Binding.ValidationRules>
<local:cIDValidationRule/>
</Binding.ValidationRules>
</Binding>
</Label.Content>
</Label>
<Label x:Name="lblErrorMessage" Content="No Error Yet"/>
</StackPanel>
</Window>
My Window's code:
namespace cCompleteWPFResourcesExamples
{
/// <summary>
/// Interaction logic for wValidationRule.xaml
/// </summary>
public partial class wValidationRule : Window
{
Customer cus = new Customer();
public wValidationRule()
{
InitializeComponent();
cus.ID = 0;
stkMain.DataContext = cus;
}
private void lblSource_Error(object sender, ValidationErrorEventArgs e)
{
lblErrorMessage.Content = e.Error.ErrorContent.ToString();
}
}
}
My ValidationRule:
using System.Windows.Controls;
namespace cCompleteWPFResourcesExamples
{
public class cIDValidationRule : ValidationRule
{
public override ValidationResult Validate(object value,
System.Globalization.CultureInfo cultureInfo)
{
int iValue = (int)value;
if (iValue == 0) return new ValidationResult(false, "No ID number");
return new ValidationResult(true, null);
}
}
}
The Customer object is very simple: Just a few properties.
Thanks!
James
Upvotes: 3
Views: 3756
Reputation: 2406
I had to do this to get it working for me, which I got from this site
<Binding Path="ID"
NotifyOnValidationError="True"
ValidatesOnDataErrors="true"
ValidatesOnExceptions="True"
UpdateSourceTrigger="PropertyChanged" Mode="TwoWay">
hope this helps, also watch out as the object
that gets passed through to validation was a string
in my case not an int
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
if (value is int)
{
int iValue = (int)value;
if (iValue == 0)
{
return new ValidationResult(false, "No ID number");
}
return new ValidationResult(true, null);
}
else if (value is string)
{
string strValue = (string)value;
if (String.IsNullOrEmpty(strValue) || strValue == "0")
{
return new ValidationResult(false, "No ID number");
}
}
return new ValidationResult(true, null);
}
* Update **
I forgot I also had to add this in for it to trigger
public wValidationRule()
{
InitializeComponent();
cus.ID = 0;
stkMain.DataContext = cus;
//trigger the validation.
lblSource.GetBindingExpression(Label.ContentProperty).UpdateSource();
}
Upvotes: 0
Reputation: 8791
Awww such a sad title :) :) First wpf validationrule is not doing what you want.
The binding engine checks each ValidationRule associated with a binding each time an input value (the binding target property value) is transferred to the binding source property.
Remember this:
You type something and the value is being persisted to the source => ValidationRule will fire.
You want to show something in Label and the value is being transmitted from source to Label => ValidationRule will never fire.
If you wish your example to work then take a TextBox instead and set the Binding Mode to TwoWay so you may type in something and Binding will persist the typed value to the source causing ValidationRule to fire. :)
Upvotes: 2