1
votes

I am trying to use exception validation on a cell in a DataGrid together with a style on the DataGridTextColumn's EditingElementStyle to set a tooltip with the content of the error. The error occurs but is not being caught or displayed within WPF.

The code and exception are shown below. Can someone tell me what I need to fix this?

Cheers,
Berryl

Here's the exception:

System.Windows.Data Error: 8 : Cannot save value from target back to source. 
BindingExpression:Path=Allocations[6].Amount; DataItem='ActivityViewModel' (HashCode=-938045583); 
target element is 'TextBox' (Name=''); 
target property is 'Text' (type 'String') 
TargetInvocationException:'System.Reflection.TargetInvocationException: 
Exception has been thrown by the target of an invocation. ---> 
Domain.Core.PreconditionException: An allocation must be less than one day.

Here is the xaml for the DataGridTextColumn:

<dg:DataGridTextColumn 
    ....                
    EditingElementStyle="{StaticResource cellEditStyle}"
    Binding="{Binding Allocations[6].Amount, Converter={StaticResource amtConv}, 
        ValidatesOnExceptions=True}"
                               />

And here is the style that should provide Tooltip feedback on he error:

    <Style x:Key="cellEditStyle" TargetType="{x:Type TextBox}">
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="Padding" Value="0"/>
    <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>
1

1 Answers

6
votes

It's probably a bit late, but since I'm running into the same kind of trouble, here is a work-around for further reference (tested with .NET 4.0.30319).

1) Catching the exception

While the following binding code in the original post works fine with a TextBox, for example, it doesn't with a DataGrid text cell (even though the Msn documentation states so):

<!-- Doesn't work -->
<DataGridTextColumn Binding="{Binding Path=Age, ValidatesOnExceptions=True}"
                    ...
                    />

You have to add this bit:

<DataGridTextColumn Binding="{Binding Path=Age, Mode=TwoWay, ValidatesOnExceptions=True}"
                    ...
                    />

Note that, strangely enough (to me anyway), the exception will be catched and shown with the exclamation mark in the row header. You just won't have the red border nor the possibility to apply a style without the Mode=TwoWay part.

2) Applying a style

Another difficulty is setting a style in case of error, because the editing element will close as soon as you start the validation process. So attaching a style with:

<!-- Doesn't work -->
<DataGridTextColumn Binding="{Binding Path=Age, Mode=TwoWay, ValidatesOnExceptions=True}"
                    EditingElementStyle="{StaticResource datagridTBStyle}"
                    ...
                    />

will simply not work if you want to trigger on a validation error. Likewise with a CellStyle which will not have the error flag to trig on. You have to use a trick and declare a FrameworkElement style, like this:

<DataGridTextColumn Binding="{Binding Path=Age, Mode=TwoWay, ValidatesOnExceptions=True}"
                    ElementStyle="{StaticResource datagridElemStyle}"
                    ...
                    />

Good news is you can define the style on a derived element, like a TextBlock, and benefit from their properties:

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