3

在我的 WPF 应用程序中,我只想在用户编辑/输入/聚焦控件后显示验证装饰器。这样,用户就有机会在该字段中提供有效输入,并且只有当他们选择不提供时,才会显示验证。

我们希望鼓励填写每个字段,以便在表单首次打开时指示必填字段可能会规避用户将倾向于立即完成他们需要的内容,以摆脱可能也规避的大红色验证错误表格的流程。

有没有办法知道控件是否已经保持焦点?附加财产可能有用吗?

如果它有助于提供更具体的响应:这是我当前的验证样式,显示红色边框[如果控件有边框]和带有错误消息工具提示的小感叹号(真的很标准):

<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>
4

1 回答 1

8

您可以将附加行​​为与附加属性结合起来执行此操作。附加行为,ObserveFocus将订阅GotFocus事件并在事件处理程序中将HasHeldFocus附加属性设置为True

它可以用于像这样在 ViewModel 中设置属性

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

这是一个示例,说明如何使用它来更改已聚焦Background后的 aButton

<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>

HasHeldFocus行为

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);
    }
}

更新

在您的情况下,您可以将Validation.HasErrorTrigger 替换为 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>
于 2011-02-23T22:14:38.857 回答