Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does WPF Style to show validation errors in ToolTip work for a TextBox but fails for a ComboBox?

I am using a typical Style to display validation errors as a tooltip from IErrorDataInfo for a textbox as shown below and it works fine.

    <Style TargetType="{x:Type TextBox}">         <Style.Triggers>             <Trigger Property="Validation.HasError" Value="true">                 <Setter Property="ToolTip"                 Value="{Binding RelativeSource={RelativeSource Self},             Path=(Validation.Errors)[0].ErrorContent}"/>             </Trigger>         </Style.Triggers>     </Style> 

But when i try to do the same thing for a ComboBox like this it fails

    <Style TargetType="{x:Type ComboBox}">         <Style.Triggers>             <Trigger Property="Validation.HasError" Value="true">                 <Setter Property="ToolTip"                 Value="{Binding RelativeSource={RelativeSource Self},             Path=(Validation.Errors)[0].ErrorContent}"/>             </Trigger>         </Style.Triggers>     </Style> 

The error I get in the output window is:

System.Windows.Data Error: 17 : Cannot get 'Item[]' value (type 'ValidationError') from '(Validation.Errors)' (type 'ReadOnlyObservableCollection`1'). BindingExpression:Path=(0)[0].ErrorContent; DataItem='ComboBox' (Name='ownerComboBox'); target element is 'ComboBox' (Name='ownerComboBox'); target property is 'ToolTip' (type 'Object') ArgumentOutOfRangeException:'System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.Parameter name: index'

Oddly it also attempts to make invalid Database changes when I close the window if I change any ComboBox values (This is also when the binding error occurs)!!!

Cannot insert the value NULL into column 'EmpFirstName', table 'OITaskManager.dbo.Employees'; column does not allow nulls. INSERT fails. The statement has been terminated.

Simply by commenting the style out everyting works perfectly. How do I fix this?

Just in case anyone needs it one of the comboBox' xaml follows:

<ComboBox ItemsSource="{Binding Path=Employees}"                    SelectedValuePath="EmpID"                                          SelectedValue="{Binding Path=SelectedIssue.Employee2.EmpID,                      Mode=OneWay, ValidatesOnDataErrors=True}"                    ItemTemplate="{StaticResource LastNameFirstComboBoxTemplate}"                   Height="28" Name="ownerComboBox" Width="120" Margin="2"                    SelectionChanged="ownerComboBox_SelectionChanged" />   <DataTemplate x:Key="LastNameFirstComboBoxTemplate">     <TextBlock>           <TextBlock.Text>               <MultiBinding StringFormat="{}{1}, {0}" >                     <Binding Path="EmpFirstName" />                     <Binding Path="EmpLastName" />               </MultiBinding>          </TextBlock.Text>     </TextBlock> </DataTemplate> 

SelectionChanged: (I do plan to implement commanding before long but, as this is my first WPF project I have not gone full MVVM yet. I am trying to take things in small-medium sized bites)

// This is done this way to maintain the DataContext Integrity  // and avoid an error due to an Object being "Not New" in Linq-to-SQL private void ownerComboBox_SelectionChanged(object sender,                                              SelectionChangedEventArgs e) {     Employee currentEmpl = ownerComboBox.SelectedItem as Employee;     if (currentEmpl != null &&          currentEmpl != statusBoardViewModel.SelectedIssue.Employee2)     {         statusBoardViewModel.SelectedIssue.Employee2 = currentEmpl;     } } 
like image 799
Mike B Avatar asked Feb 14 '10 09:02

Mike B


People also ask

What is WPF data validation?

Syncfusion WPF input controls allow you to validate user input and display hints if validation fails. If the user input is invalid, a default red border will be shown around the UIElement.


2 Answers

Your getting this error because when you validation finds that there are no issues, the Errors collection returns with no items, and the following binding logic fails:

Path=(Validation.Errors)[0].ErrorContent}" 

you are accessing the validation collection by a specific index. I'm currently working on a DataTemplate Suggestion for replacing this text.

I love that Microsoft listed this in their standard example of a validation template.

update so replace the code above with the following, and the binding logic will know how to handle the empty validationresult collection:

Path=(Validation.Errors).CurrentItem.ErrorContent}" 

(following xaml was added as a comment)

<ControlTemplate x:Key="ValidationErrorTemplate" TargetType="Control">     <StackPanel Orientation="Horizontal">         <TextBlock Foreground="Red" FontSize="24" Text="*"                     ToolTip="{Binding .CurrentItem}">         </TextBlock>         <AdornedElementPlaceholder>         </AdornedElementPlaceholder>     </StackPanel> </ControlTemplate> 

Update in 2019

As of currently, the correct path syntax to use is:

Path=(Validation.Errors)/ErrorContent 
like image 168
Nathan Tregillus Avatar answered Oct 05 '22 20:10

Nathan Tregillus


I think this is the best way:

Path=(Validation.Errors)/ErrorContent 

/ is actually equal to CurrentItem by @Nathan

In my case, CurrentItem is a no go.

like image 23
Altiano Gerung Avatar answered Oct 05 '22 18:10

Altiano Gerung