0

One can only use a ValidationRule with binding; what's a good way to use Validation.ErrorTemplate with Grid based upon its contents rather than its properties like width, etc.?

puzzlepiece87
  • 1,537
  • 2
  • 19
  • 36

1 Answers1

0

Use the Tag property.

I had a group of radio buttons inside my grid that I wanted to ensure had at least one checked member. If not, I wanted to highlight the entire grid with an Validation.ErrorTemplate to alert the user that they had not finished a section of the form they are filling out.

So I did this in XAML:

<Grid
    Name="GridReportType"
    Margin="0,20,0,0">
    <Grid.Tag>
        <Binding Path="ReportTypeSelected" 
            UpdateSourceTrigger="PropertyChanged" 
            Mode="OneWayToSource">
            <!--Validation rules only fire when target (WPF property) updates source (class property)-->
            <Binding.ValidationRules>
                <parent:FailIfFalse/>
            </Binding.ValidationRules>
        </Binding>
    </Grid.Tag>
</Grid

with this in the window's code behind constructor:

this.GridReportType.Tag = false;

and with this ValidationRule:

public class FailIfFalse : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        if (!((bool)value))
        {
            return new ValidationResult(false, "Required");
        }
        else
        {
            return new ValidationResult(true, null);
        }
    }
}

and with this error template:

<Grid.Style>
    <Style>
        <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="True">
            <Setter Property="Validation.ErrorTemplate">
            <Setter.Value>
                <ControlTemplate>
                <DockPanel>
                    <TextBlock DockPanel.Dock="Bottom"
                       Foreground="Red"
                       FontSize="24"
                       FontStyle="Italic"
                       HorizontalAlignment="Center"
                       Text="{Binding ElementName=cantBeEmptyAdorner,
                        Path=AdornedElement.(Validation.Errors),
                        Converter={StaticResource GetLatestValidationError}}"/>
                    <Border BorderBrush="Red"
                        BorderThickness="1"
                        Margin="-1">
                    <AdornedElementPlaceholder x:Name="cantBeEmptyAdorner"/>
                    </Border>
                </DockPanel>
                </ControlTemplate>
            </Setter.Value>
            </Setter>
        </Trigger>
        </Style.Triggers>
    </Style>
</Grid.Style>
puzzlepiece87
  • 1,537
  • 2
  • 19
  • 36
  • Why not use a DataTrigger? https://learn.microsoft.com/en-us/dotnet/api/system.windows.datatrigger – quaabaam Aug 14 '20 at 22:54
  • 1
    @quaabaam I tried to, and maybe there's a good way to do it! I'm new at this. The problem I hit when trying DataTrigger was that my DataTrigger couldn't seem to bring about my Validation.ErrorTemplate, because it doesn't have anything to do with Validation. Grid doesn't have a Template property, and I wanted to use a Template to add the DockPanel underneath the Grid. How would you have approached it? – puzzlepiece87 Aug 14 '20 at 23:05