Search code examples
wpfvalidationtoolbardatatrigger

How to invoke DataTrigger on a Toolbar Button during Validate.HasError


I have implemented the following xaml code to disable a toolbar button when Validation.HasError based on the text entered into the ComboBox based on the UserAccountValidationRule

The core xaml code is shown here:

    <telerik:RadComboBox
        x:Name="DataProviderComboBox" Width="120" Height="23" IsEditable="True" DataContext="{StaticResource MainWindowViewModel}">
        <telerik:RadComboBox.Text>
            <Binding Mode="TwoWay" Path="InputString">
                <Binding.ValidationRules>
                    <validationRules:UserAccountValidationRule/>
                </Binding.ValidationRules>
            </Binding>
        </telerik:RadComboBox.Text>
    </telerik:RadComboBox>

    <telerik:RadButton
        Name="ToolbarButton" Width="74" HorizontalAlignment="Left" VerticalAlignment="Top" Content="Button">
        <telerik:RadButton.Style>
            <Style TargetType="{x:Type telerik:RadButton}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding (Validation.HasError), ElementName=DataProviderComboBox}" Value="true" >
                        <Setter Property="IsEnabled" Value="false"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </telerik:RadButton.Style>
    </telerik:RadButton>

</telerik:RadToolBar>

<Grid>
    <telerik:RadButton 
        Name="OrdinaryButton" Width="74" HorizontalAlignment="Left" VerticalAlignment="Top" Content="Button" Margin="252,26,0,0">
        <telerik:RadButton.Style>
            <Style TargetType="{x:Type telerik:RadButton}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding (Validation.HasError), ElementName=DataProviderComboBox}" Value="true" >
                        <Setter Property="IsEnabled" Value="false"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </telerik:RadButton.Style>
    </telerik:RadButton>
</Grid>

What I would like is for the DataTrigger in the ToolBarButton to be invoked, but it is not.

I did a check on the validation by creating a second OrdinarryButton, and hooked this up to the validation, and this worked fine. It seems as if the DataTrigger does not work if the button is a toolbar item.

Can anyone explain how to get this to work?


Solution

  • So, as it turns out, if the button is an OrdinaryButton control, then the DataTrigger will be invoked and the button will be disabled on Validation.HasError = true via the xaml code below:

    <Grid>
        <telerik:RadButton 
            Name="OrdinaryButton" Width="74" HorizontalAlignment="Left" VerticalAlignment="Top" Content="Button" Margin="252,26,0,0">
            <telerik:RadButton.Style>
                <Style TargetType="{x:Type telerik:RadButton}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding (Validation.HasError), ElementName=DataProviderComboBox}" Value="true" >
                            <Setter Property="IsEnabled" Value="false"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </telerik:RadButton.Style>
        </telerik:RadButton>
    </Grid>
    

    However, if the button control is placed inside a ToolbarButton, the same xaml code will not disable the Toolbar button:

        <telerik:RadComboBox
            x:Name="DataProviderComboBox" Width="120" Height="23" IsEditable="True" DataContext="{StaticResource MainWindowViewModel}">
            <telerik:RadComboBox.Text>
                <Binding Mode="TwoWay" Path="InputString">
                    <Binding.ValidationRules>
                        <validationRulesParameterPass:UserAccountValidationRule/>
                    </Binding.ValidationRules>
                </Binding>
            </telerik:RadComboBox.Text>
        </telerik:RadComboBox>
    
        <telerik:RadButton
            Name="ToolbarButton" Width="74" HorizontalAlignment="Left" VerticalAlignment="Top" Content="Button">
            <telerik:RadButton.Style>
                <Style TargetType="{x:Type telerik:RadButton}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding (Validation.HasError), ElementName=DataProviderComboBox}" Value="true" >
                            <Setter Property="IsEnabled" Value="false"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </telerik:RadButton.Style>
        </telerik:RadButton>
    
    </telerik:RadToolBar>
    

    I find this very peculiar, and it might be a previously undiscovered bug? If anyone knows whether this is expected behavior or not, and has a reason for the observed behavior, please feel free to post.

    In the meantime, I spent some time developing an acceptable workaround.

    In this case I modified the <validationRules:UserAccountValidationRule/> to take a parameter that passes a single boolean IsEnabled property:

                    <Binding.ValidationRules>
                        <validationRulesParameterPass:UserAccountValidationRule>
                            <validationRulesParameterPass:UserAccountValidationRule.AccountValidationParameter>
                                <validationRulesParameterPass:AccountValidationParameter IsEnabled="{Binding IsButtonEnabled, Source={StaticResource MainWindowViewModel}}" />
                            </validationRulesParameterPass:UserAccountValidationRule.AccountValidationParameter>
                        </validationRulesParameterPass:UserAccountValidationRule>
                    </Binding.ValidationRules>
    

    I also binded the IsButtonEnabled dependency property property to the ToolBar Button item's IsEnabled property.

    Then, inside the UserAccountValidationRule, based on whether the value is valid or not, the IsButtonEnabled property will be set to true or false. As this DependencyProperty is connected to the Toolbar Button's, if the validation sets this true, the button's IsEnabled property will also be set to true, and vice versa.

    public class UserAccountValidationRule : ValidationRule
    {
        private AccountValidationParameter _accountValidationParameter;
    
        public UserAccountValidationRule()
        {
    
        }
        public AccountValidationParameter AccountValidationParameter
        {
            get { return _accountValidationParameter; }
            set { _accountValidationParameter = value; }
        }
    
        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
        {
    
            if ( !string.IsNullOrEmpty(value as string) && value as string == "good")
            {
                AccountValidationParameter.IsEnabled = true;
                return new ValidationResult(true, null);
            }
            else
            {
    
                AccountValidationParameter.IsEnabled = false;
    
                return new ValidationResult(false, "bad string.");
            }
        }
    }
    

    Problem solved.