1

I created a WPF (.Net 4) UserControl containing some ComboBoxes and a TextBox. In XAML, some ValidationRules are bound to the TextBox. If the TextBox contains invalid data, a red frame is shown, and the tooltip is set to the error description. Works well.

Next, I placed two instances of that UserControl on a form, and added a button. In XAML, the button is connected to a RelayCommand of the ViewModel. Now I want the button to be enabled only when both of the UserControls contain valid data only.

Not a problem, I thought, let me use a strategy which works elsewhere. I added a trigger:

    <Button Content="_OK" ... Command="{Binding Path=OKCommand}">
        <Button.Style>
            <Style TargetType="{x:Type Button}">
                <Setter Property="IsEnabled" Value="false" />
                <Style.Triggers>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding ElementName=cascadingComboFrom, Path=(Validation.HasError)}" Value="false" />
                            <Condition Binding="{Binding ElementName=cascadingComboTo, Path=(Validation.HasError)}" Value="false" />
                        </MultiDataTrigger.Conditions>
                        <Setter Property="IsEnabled" Value="true" />
                    </MultiDataTrigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
    </Button>

But there is a catch: Validation.HasError is always false for the UserControls - the Validation failed for an element inside the UserControl, not for the UserControl proper.

I know that I can register the Click event of the button, check the validity there using the method shown in Detecting WPF Validation Errors, and prevent the execution of the RelayCommand by setting the Handled property of the RoutedEventArgs to true. But that looks more like WTF than WPF.

What do you suggest? How can I retrieve the Validation Errors of the UserControl's children? Or how can I get them in the RelayCommand's CanExecute method? Or some other tricks?

Community
  • 1
  • 1
Bernhard Hiller
  • 2,163
  • 2
  • 18
  • 33

2 Answers2

0

You can set a property on the command binding called ValidatesOnDataErrors.

Implementation would look something like this:

 <Button Content="_OK" Command="{Binding, Path=OKCommand, ValidatesOnDataErrors=True}"/>

You can read more about it here.

Thomas Bouman
  • 608
  • 4
  • 17
0

The Button.IsEnabled property is already hard wired to the CanExecute method of your RelayCommand, so all you need to do is to set that return value to false when the form fields are invalid:

private bool CanExecute(object commandParameter)
{
    return areFormFieldsValid;
}

Now, how you set the bool areFormFieldsValid variable to true or false is up to you... there are several ways of doing that. Personally, I prefer to use the IDataErrorInfo interface, which has a handy Error property that you can check. There are many online tutorial on how to implement this, so I won't repeat that here... however, the end result is something like this:

private bool CanExecute(object commandParameter)
{
    return string.IsNullOrEmpty(yourDataObject.Error);
}
Sheridan
  • 68,826
  • 24
  • 143
  • 183