WPF Validation Credentials - Only show if the control held focus until

In my WPF application, I want to show only the advertiser checks after the user has edited / entered / focused controls. Thus, the user is given the opportunity to enter a valid input in the field and only if they do not want to, then a confirmation will be displayed.

We want each field to be filled in so as to indicate the required fields, when the first form opens, it can circumvent this, because immediately the user will be inclined to simply complete what they need to get rid of the big red validation errors, which can also bypass stream form.

Is there a way to find out if the control still holds focus? Can a related property work?

In case this helps to get a more specific answer: here is my current validation style, which displays a red border [if the control has a border] and a small exclamation mark with a hint for an error message (pretty standard standard):

<Style TargetType="Control">
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="true">
            <Setter Property="ToolTip"
                    Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                    Path=(Validation.Errors).CurrentItem.ErrorContent}"/>

            <Setter Property="Validation.ErrorTemplate">
                <Setter.Value>
                    <ControlTemplate>
                        <DockPanel LastChildFill="true">
                            <Image Source="../Resources/Icons/Error.ico" Margin="4" Width="15" ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}" />
                            <AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
                                <Border BorderBrush="red" BorderThickness="1" Visibility="{Binding ElementName=customAdorner, Path=AdornedElement.BorderThickness, Converter={StaticResource hasBorderToVisibilityConverter}}" />
                            </AdornedElementPlaceholder>
                        </DockPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Trigger>
        <Trigger Property="IsVisible" Value="False">
            <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
        </Trigger>
    </Style.Triggers>
</Style>
+3
source share
1 answer

To do this, you can combine Attached Behavior with Attached Property. The attached behavior ObserveFocuswill be subscribed to the event GotFocus, and in the event handler, set the HasHeldFocusAttached Property toTrue

It can be used to set a property in the ViewModel, as shown.

<Button local:HasHeldFocusBehavior.ObserveFocus="True"
        local:HasHeldFocusBehavior.HasHeldFocus="{Binding HasHeldFocus, 
                                                          Mode=OneWayToSource}"/>

Here is an example of how it could be used to change Backgroundfor Buttonafter focusing it

<Style TargetType="Button">
    <Setter Property="Background" Value="Red"/>
    <Setter Property="local:HasHeldFocusBehavior.ObserveFocus" Value="True"/>
    <Style.Triggers>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},
                                       Path=(local:HasHeldFocusBehavior.HasHeldFocus)}"
                        Value="True">
            <Setter Property="Background" Value="Green"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

HasHeldFocusBehavior

public static class HasHeldFocusBehavior
{
    public static readonly DependencyProperty ObserveFocusProperty =
        DependencyProperty.RegisterAttached("ObserveFocus",
                                            typeof(bool),
                                            typeof(HasHeldFocusBehavior),
                                            new UIPropertyMetadata(false, OnObserveFocusChanged));
    public static bool GetObserveFocus(DependencyObject obj)
    {
        return (bool)obj.GetValue(ObserveFocusProperty);
    }
    public static void SetObserveFocus(DependencyObject obj, bool value)
    {
        obj.SetValue(ObserveFocusProperty, value);
    }
    private static void OnObserveFocusChanged(DependencyObject dpo,
                                              DependencyPropertyChangedEventArgs e)
    {
        UIElement element = dpo as UIElement;
        element.Focus();
        if ((bool)e.NewValue == true)
        {
            SetHasHeldFocus(element, element.IsFocused);
            element.GotFocus += element_GotFocus;
        }
        else
        {
            element.GotFocus -= element_GotFocus;
        }
    }
    static void element_GotFocus(object sender, RoutedEventArgs e)
    {
        UIElement element = sender as UIElement;
        SetHasHeldFocus(element, true);
    }

    private static readonly DependencyProperty HasHeldFocusProperty =
        DependencyProperty.RegisterAttached("HasHeldFocus",
                                            typeof(bool),
                                            typeof(HasHeldFocusBehavior),
                                            new UIPropertyMetadata(false));
    public static void SetHasHeldFocus(DependencyObject element, bool value)
    {
        element.SetValue(HasHeldFocusProperty, value);
    }
    public static bool GetHasHeldFocus(DependencyObject element)
    {
        return (bool)element.GetValue(HasHeldFocusProperty);
    }
}

Update

Validation.HasError MultiTrigger

<Style TargetType="Control">
    <Style.Triggers>
        <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
                <Condition Binding="{Binding RelativeSource={RelativeSource Self},
                                             Path=(Validation.HasError)}"
                           Value="True"/>
                <Condition Binding="{Binding RelativeSource={RelativeSource Self},
                                             Path=(local:HasHeldFocusBehavior.HasHeldFocus)}"
                           Value="True"/>
            </MultiDataTrigger.Conditions>
            <!-- Setters.. -->
        </MultiDataTrigger>
        <!-- ... -->
    </Style.Triggers>
</Style>
+8

Source: https://habr.com/ru/post/1794259/


All Articles