Is it possible to change properties on the validation error template in WPF?

Viewed 33

I'm using the Validation.ErrorTemplate property in my XAML view to display an icon next to any invalid control.

For one particular control in my view, I need to set the icon in a slightly different position. Is it possible for me to use the same control template, but somehow update the Margin property for a certain control?

Here's my (abridged) code:

<UserControl>
    <UserControl.Resources>
        <ControlTemplate x:Key="ValidationTemplate" TargetType="Control">
            <DockPanel>
                <Grid
                    DockPanel.Dock="Right"
                    Height="16"
                    Margin="10,0,0,0"
                    VerticalAlignment="Center"
                    Width="16">
                    <Image
                        AutomationProperties.AutomationId="_validationIcon"
                        Source="{x:Static icons:Icons.ValidationIcon}"
                        ToolTip="{Binding Path=ErrorContent}" />
                </Grid>
                <AdornedElementPlaceholder />
            </DockPanel>
        </ControlTemplate>

        <ItemsControl Validation.ErrorTemplate="{StaticResource ValidationTemplate}" />
</UserControl>

The only way I've managed to achieve what I need is to create a new ControlTemplate just for the control that requires a different icon placement. I would rather reuse my original control template if possible.

1 Answers

I had exactly same requirement in my old project. I solved it using an attached dependency property:

public static class ErrorTemplateProperties
{
    public static readonly DependencyProperty ErrorMarginProperty = DependencyProperty.RegisterAttached
    (
        "ErrorMargin",
        typeof(Thickness),
        typeof(ErrorTemplateProperties),
        new FrameworkPropertyMetadata(new Thickness(10,0,0,0))
    );

    public static Thickness GetErrorMargin(DependencyObject obj)
    {
        return (Thickness)obj.GetValue(ErrorMarginProperty);
    }

    public static void SetErrorMargin(DependencyObject obj, Thickness value)
    {
        obj.SetValue(ErrorMarginProperty, value);
    }
}

add it to ValidationTemplate:

<ControlTemplate x:Key="ValidationTemplate" TargetType="Control">
    <DockPanel>
        <Grid
            DockPanel.Dock="Right"
            Margin="{Binding Path=AdornedElement.(local:ErrorTemplateProperties.ErrorMargin), ElementName=ui}"
            Height="16"
            VerticalAlignment="Center"
            Width="16">
            <Image
                AutomationProperties.AutomationId="_validationIcon"
                Source="{x:Static icons:Icons.ValidationIcon}"
                ToolTip="{Binding Path=ErrorContent}" />
        </Grid>

        <AdornedElementPlaceholder x:Name="ui"/>
    </DockPanel>
</ControlTemplate>

and then optionally change on required ui elements:

<ItemsControl helpers:ErrorTemplateProperties.ErrorMargin="0,0,0,0" 
              Validation.ErrorTemplate="{StaticResource ValidationTemplate}" />

I also found a workaround with DynamicResources but attached DP are more flexible and laconic in my opinion

Related