I am working on a .NET 4.0 project that deals with validation of the range of a particular data type. For example, a 32 bit int should only be between Int32.MinValue and Int32.MaxValue or any other value defined by the application. I want to be able to specify data types and ranges on a custom validator so they can be called directly from the xaml through binding: <CheckIfValueRangeValidator>
This is what I have in mind, I am not sure it will work or if it can even be done through the xaml.
class CheckIfValueInRangeValidator<T> : ValidationRule
{
public T Max { get; set; }
public T Min { get; set; }
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
// Implementation...
}
}
My bad, actually you cannot use x:TypeArguments as it will raise x:TypeArguments is not allowed in object elements for XAML version lower than 2009, it's valid only on loose XAML files or the root element (Window in my case) ...
http://msdn.microsoft.com/en-us/library/ms750476.aspx
But as a workaround you could use the following pattern :
<TextBox x:Name="textBox1">
<Binding Path="MyValue"
Source="{StaticResource MyObject}"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<wpfApplication6:MyValidationRule ObjectType="{x:Type system:Int32}" />
</Binding.ValidationRules>
</Binding>
</TextBox>
Code behind :
public class MyObject
{
public object MyValue { get; set; }
}
public class MyValidationRule : ValidationRule
{
public Type ObjectType { get; set; }
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
throw new NotImplementedException();
}
}
Take a look at this one too : Using a Generic IValueConverter from XAML
@Blam comment is worthwhile to consider, a range to check generally applies for an integer or a double, for other types I'd say you could just add a boolean that return the validity of that object and perform such validation inside the object itself.
For numbers you have RangeAttribute but it's not really part of the WPF validation infrastructure.
You also have an another option for validation : INotifyDataErrorInfo validation takes place inside the object in this case.
I wrote a lengthy answer here : https://softwareengineering.stackexchange.com/questions/203590/is-there-an-effective-way-for-creating-complex-forms you might find something useful on it.
From my experience I'd say that a generic validating rule is probably not wise to do.
You should edit your question to be less generic ;-) but rather more specific, you'd get more help from people here. Give one or two concrete cases of the objects you are trying to validate.
EDIT
You can also use a BindingGroup for validating an object :
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void TextBox1_OnTextChanged(object sender, TextChangedEventArgs e)
{
grid.BindingGroup.CommitEdit();
}
}
public class Indices
{
public int ColorIndex { get; set; }
public string ColorPrefix { get; set; }
public int GradientIndex { get; set; }
public string GradientPrefix { get; set; }
}
public class ValidateMe : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
var bindingGroup = value as BindingGroup;
var o = bindingGroup.Items[0] as Indices;
return new ValidationResult(true, null);
}
}
<Window x:Class="WpfApplication6.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication6="clr-namespace:WpfApplication6"
Title="MainWindow"
Width="525"
Height="350">
<Window.Resources>
<wpfApplication6:Indices x:Key="Indices"
ColorIndex="1"
ColorPrefix="MyColor"
GradientIndex="1"
GradientPrefix="MyGradient" />
</Window.Resources>
<Grid x:Name="grid" DataContext="{StaticResource Indices}">
<Grid.BindingGroup>
<BindingGroup>
<BindingGroup.ValidationRules>
<wpfApplication6:ValidateMe />
</BindingGroup.ValidationRules>
</BindingGroup>
</Grid.BindingGroup>
<TextBox TextChanged="TextBox1_OnTextChanged">
<Binding Path="ColorIndex" UpdateSourceTrigger="PropertyChanged" />
</TextBox>
</Grid>
</Window>
Using RangeAtribute :
private void test()
{
Indices indices = new Indices();
indices.ColorIndex = 20;
var validationContext = new ValidationContext(indices);
var validationResults = new List<System.ComponentModel.DataAnnotations.ValidationResult>();
var tryValidateObject = Validator.TryValidateObject(indices, validationContext, validationResults,true);
}
public class Indices
{
[Range(1, 10)]
public int ColorIndex { get; set; }
public string ColorPrefix { get; set; }
public int GradientIndex { get; set; }
public string GradientPrefix { get; set; }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With