views:

16

answers:

1

I (believe) I'm wiring up DataBinding Validation in a textbook manner, but it just isn't working - at all.

In the debugger, the Validate(object value, CultureInfo cultureInfo) method is never called.

What gives? Also, for bonus points, any pointers on debugging WPF would be awesome.

I'm posting my XAML and the class in question

<UserControl x:Class="FooControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:Foo.Controls"
         mc:Ignorable="d" 
         d:DesignWidth="300">
<Grid Name="GridFoo">
    <Grid.Resources>
        <local:ValueConverter x:Key="MyConverter" />
    </Grid.Resources>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" />
    </Grid.ColumnDefinitions>
    <TextBox Name="TextBoxScalar" Grid.Column="0" TextAlignment="Right">
        <TextBox.Text>
            <Binding Mode="OneWay" Path="Scalar" NotifyOnValidationError="True" ValidatesOnDataErrors="True" ValidatesOnExceptions="True">
                <Binding.ValidationRules>
                    <local:ScalarValidationRule />
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>
    <TextBlock Name="TextBlockUnit" Grid.Column="1" TextAlignment="Left" Padding="3">
        <Hyperlink>
            <!-- Use a custom converter here b/c generics break wpf... -->
            <Run Text="{Binding Mode=OneWay, Path=Unit, Converter={StaticResource MyConverter}}" />
        </Hyperlink>
    </TextBlock>
</Grid>

ValidationRule

public class ScalarValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        string number = value as string;
        double d;
        return new ValidationResult(Double.TryParse(number, NumberStyles.Any, cultureInfo, out d),
            String.Format("\"{0}\" is not a number.", number));
    }
}
+1  A: 

You are adding the ValidationRule to a one-way binding. One-way bindings never push a value to the source, so there is nothing to validate and your ValidationRule is never called. If you want to validate data entered by the user, set Mode="TwoWay" on your binding. You can also omit the Mode attribute completely, since TextBox.Text binds two-way by default.

If you really do want a one-way binding and you want validation to occur when the value is pushed from the source (Scalar) to the target (TextBox.Text), then set ValidatesOnTargetUpdated to True on the ValidationRule. You can either do this in XAML or in the constructor of your ValidationRule class.

Quartermeister
Asked and answered. Thanks.
pomeroy