在我的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>
最佳答案
您可以将“附加行为”与“附加属性”结合使用。附加行为ObserveFocus
将订阅GotFocus
事件,并在事件处理程序中将HasHeldFocus
附加属性设置为True
它可以像这样在ViewModel中设置属性
<Button local:HasHeldFocusBehavior.ObserveFocus="True"
local:HasHeldFocusBehavior.HasHeldFocus="{Binding HasHeldFocus,
Mode=OneWayToSource}"/>
这是一个示例,说明如何在聚焦后将其用于更改
Background
的Button
<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);
}
}
更新
您可以使用MultiTrigger替换
Validation.HasError
触发器<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>