Datepicker验证和AdornedElement.IsKeyboardFocused

时间:2015-03-29 14:35:54

标签: c# wpf

我的表单上有一个DatePicker。当用户键入无效日期时,控件将获得红色边框。但是,我还想在它旁边显示错误。

<Style TargetType="{x:Type DatePicker}">
    <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <StackPanel Orientation="Horizontal">
                    <Border BorderThickness="1" BorderBrush="#FFdc000c" VerticalAlignment="Top">
                        <Grid>
                            <AdornedElementPlaceholder x:Name="adorner" Margin="-1"/>
                        </Grid>
                    </Border>
                    <Border x:Name="errorBorder" Background="#FFdc000c" Margin="8,0,0,0"
                            Opacity="0" CornerRadius="0"
                            IsHitTestVisible="False"
                            MinHeight="24" >
                        <TextBlock Text="{Binding ElementName=adorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"
                                   Foreground="White" Margin="8,2,8,3" TextWrapping="Wrap" VerticalAlignment="Center"/>
                    </Border>
                </StackPanel>
                <ControlTemplate.Triggers>
                    <DataTrigger Value="True">
                        <DataTrigger.Binding>
                            <Binding ElementName="adorner" Path="AdornedElement.IsKeyboardFocused" />
                        </DataTrigger.Binding>
                        <DataTrigger.EnterActions>
                            <BeginStoryboard x:Name="fadeInStoryboard">
                                <Storyboard>
                                    <DoubleAnimation Duration="00:00:00.15"
                                                     Storyboard.TargetName="errorBorder"
                                                     Storyboard.TargetProperty="Opacity"
                                                     To="1"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </DataTrigger.EnterActions>
                        <DataTrigger.ExitActions>
                            <StopStoryboard BeginStoryboardName="fadeInStoryboard"/>
                            <BeginStoryboard x:Name="fadeOutStoryBoard">
                                <Storyboard>
                                    <DoubleAnimation Duration="00:00:00"
                                                     Storyboard.TargetName="errorBorder"
                                                     Storyboard.TargetProperty="Opacity"
                                                     To="0"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </DataTrigger.ExitActions>
                    </DataTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    </Style>

在我的app.xaml中,我将其包括在内:

<ResourceDictionary>
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="pack://application:,,,/<assembly>.App;component/Styles/DatePicker.xaml" />
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

日期选择器旁边没有显示验证文本。我做错了什么?

更新
它出现此问题与在动画中使用AdornedElement.IsKeyboardFocused有关。如果我删除动画并将不透明度设置为1,则会显示验证,但这显然不是我想要在这里实现的。但是,此代码适用于其他控件,如文本框,复选框,..

有没有其他方法可以让它发挥作用?

2 个答案:

答案 0 :(得分:5)

DatePicker是一个控件,其中IsKeyboardFocused不会填充属性(请尝试WPF Inspector自行检查)。可能是因为它可能不是典型的输入控件,键盘焦点可能是日历按钮或实际文本框。 该分辨率用于IsKeyboarFocusWithin。

<DataTrigger.Binding>
  <Binding ElementName="adorner" Path="AdornedElement.(DatePicker.IsKeyboardFocusWithin)" />
</DataTrigger.Binding>

答案 1 :(得分:0)

使用弹出窗口作为模板,您可以使用展示位置属性将其放置在控件周围。

<Popup x:Name="Popup"
               Placement="Right"
               PlacementTarget="{Binding ElementName=adorner}">
    <Grid>
        <Border Background="{DynamicResource UI.ErrorBrush}" Padding="5 4">
                        <TextBlock Text="{Binding Path=AdornedElement.(Validation.Errors)[0].ErrorContent,
                                                  RelativeSource={RelativeSource Mode=FindAncestor,
                                                                                 AncestorType={x:Type Adorner}},
                                                  FallbackValue=null, Mode=OneTime}"/>
        </Border>
    </Grid>
</Popup>

要为弹出窗口添加行为,您需要应用数据触发器,以便在需要时执行所需操作。

在顶部包含此内容

xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

并在弹出窗口中创建触发器

<i:Interaction.Triggers>
<!--  Shows Popup when TextBox has focus  -->
<ei:DataTrigger Binding="{Binding ElementName=ErrorAdorner, Path=AdornedElement.IsFocused, FallbackValue=False}" Value="True">
    <ei:ChangePropertyAction PropertyName="IsOpen"
                                         TargetObject="{Binding ElementName=Popup,
                                                                FallbackValue=null}"
                                         Value="True" />
    <ei:DataTrigger Binding="{Binding ElementName=ErrorAdorner, Path=AdornedElement.IsFocused, FallbackValue=False}" Value="False">
        <ei:ChangePropertyAction PropertyName="IsOpen"
                                         TargetObject="{Binding ElementName=Popup,
                                                                FallbackValue=null}"
                                         Value="False" />
    </ei:DataTrigger>

当错误为空时,您还希望触发器隐藏弹出窗口,因为如果它有动画(例如淡入淡出),弹出窗口中的文本将在淡出时显示为null。这可以是错误计数等于0并将动画设置为无/隐藏的单个触发器。