2

I have a textbox with a very simple ValidationRule:

<TextBox x:Name="textFirstName" Width="120">
    <TextBox.Text>
        <Binding
           Path="CurrentSelectionData.Tables[cpeople].Rows[0][FirstName]"
           UpdateSourceTrigger="PropertyChanged">
           <Binding.ValidationRules>
               <local:NonEmptyStringValidationRule ValidatesOnTargetUpdated="True"/>
           </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

public class NonEmptyStringValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        if (value == null || string.IsNullOrWhiteSpace(value.ToString()))
            return new ValidationResult(false, "Must provide a value.");

        return ValidationResult.ValidResult;
    }
}

The problem is that the red validation error border displays on start-up even though the textbox is bound to non-empty data.

Watching a breakpoint on the validation rule, I see that it is called once for an empty string (before the binding is changed to valid data) and once again after the binding updates to valid data. Sure enough, the second call returns ValidResult, yet the red border remains.

Manually clearing the textbox and typing new text into it clears the red border, but simply typing new text into it without first clearing it does not.

The one potential trickiness I can see, from reading other folks' questions, is that this TextBox is in a tab control. However, my problem is the opposite of those other folks (they weren't getting a red border despite a failed validation), nor am I moving to a different tab control at any point (which was the cause of the other issues).

Any ideas what I'm missing here?

Mike Woolf
  • 1,210
  • 7
  • 11

2 Answers2

2

It turns out that changing validated bound data during a Window's Loaded event caused the problem. In my case, the problem was solved by performing the data change during Initialized or ContentRendered instead. Initialized has the advantage of happening before the first (invalid) binding, thus avoiding a temporary red border to flash up during app load.

Mike Woolf
  • 1,210
  • 7
  • 11
  • 1
    I am currently having this same problem right now, could you show a little bit more detail on your answer about the changes you made to make this not happen? – Alexander Ventura Aug 13 '13 at 16:22
0

I tried to replicate your issue but it seems to work ok in my tests, so the problem must be with the data you are binding to as you said the validationRule is working fine.

Is the Table your binding to TwoWay?

My Test:

xaml:

<TextBox x:Name="textFirstName" Width="120" ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}">
    <TextBox.Text>
        <Binding ElementName="UI" Path="TextTest" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True" >
            <Binding.ValidationRules>
                <local:NonEmptyStringValidationRule ValidatesOnTargetUpdated="True"  />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

code:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private string _textTest;
    public string TextTest
    {
        get { return _textTest ; }
        set { _textTest = value; }
    }
}

public class NonEmptyStringValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        return (value is string && !string.IsNullOrEmpty(value.ToString()))
            ? new ValidationResult(true, null)
            : new ValidationResult(false, "Invalid Text");
    }
}
sa_ddam213
  • 42,848
  • 7
  • 101
  • 110
  • Yes, the binding is two-way. Near as I can tell, everything behaves fine except the validation display. In case it matters, the textbox is bound to a field in the only row of a DataTable in a DataSet. – Mike Woolf Jan 04 '13 at 03:46
  • More info. The problem is caused by the fact that the second binding update (the one that leads to valid data) happens during the main Window's Load event handler. I won't bother you with the exact mechanism unless you need that, but suffice it to say that delaying the property change that leads to the binding update until after the app is fully open avoids the problem. Does someone have an explanation for this? – Mike Woolf Jan 04 '13 at 05:22