显示错误,控制后向下移动

时间:2010-11-12 07:02:50

标签: wpf validation templates styles

所以我想在输入无效时显示一条消息,假设我想要一个ToolTip以外的东西,这些东西一直存在,直到错误得到纠正。我试过ErrorTemplate

<Style TargetType="{x:Type TextBox}">
    <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <StackPanel>
                    <Border BorderBrush="Red" BorderThickness="1">
                        <AdornedElementPlaceholder x:Name="adornedErrorElement" />
                    </Border>
                    <Label Background="Red" Foreground="White" FontSize="9" Content="{Binding ElementName=adornedErrorElement, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" />
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<StackPanel Margin="20">
    <TextBlock Text="Name" />
    <TextBox Text="{Binding Name}" />

    <TextBlock Text="Email" />
    <TextBox Text="{Binding Path=Email, ValidatesOnDataErrors=True}" />

    <Button Content="Submit" />
</StackPanel>

我得到了

alt text

标签后面的元素重叠。我怎样才能使它像stackpanel中的另一个元素一样工作?

更新:使用VSM

现在,我想进一步向上和向下动画错误标签。我正在考虑VSM跟随@robertos回答。我尝试在Blend中实现。我遇到的一些问题。我试过了

<ControlTemplate TargetType="{x:Type TextBox}">
    <StackPanel Orientation="Vertical">
        <Microsoft_Windows_Themes:ListBoxChrome ...>
        <VisualStateManager.VisualStateGroups>
                ...
        </VisualStateManager.VisualStateGroups>
        <ScrollViewer ... />
        </Microsoft_Windows_Themes:ListBoxChrome>
        <Label Content="Error Here" />
    </StackPanel>
</ControlTemplate>

然后我在Blend中失去了对VisualStates的访问权限。然后我试了

<Microsoft_Windows_Themes:ListBoxChrome>
    <StackPanel>
        <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Margin="2,0,-2,0"/>
    <TextBlock x:Name="textBlock" Background="Red" Foreground="White" FontWeight="Bold" Text="Hello" Visibility="Collapsed" />
    </StackPanel>
</Microsoft_Windows_Themes:ListBoxChrome>

不理想,因为StackPanel位于边框内。我对动画的尝试看起来也很奇怪

http://screenr.com/byk

http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,115,0'width ='560'height ='345'&gt; http:// screenr .com / Content / assets / screenr_1116090935.swf'&gt; http://screenr.com/Content/assets/screenr_1116090935.swf'flashvars ='i = 130553'allowFullScreen ='true'width ='560'height ='345 'pluginspage ='http://www.macromedia.com/go/getflashplayer'&gt;

第一,我必须隐藏标签而不是折叠动画只是不透明度。我希望标签看起来像是从文本框中出来的

2 个答案:

答案 0 :(得分:4)

该元素必须是VisualTree中相同StackPanel的一部分,而Validation.ErrorTemplate并非如您所注意到的那样。实现此目的的一种方法是重新模板TextBox并为折叠错误标签设置位置,该标签将在Validation.HasError上变为可见。您需要添加对PresentationFramework.Aero的引用。

xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"

的Xaml

<LinearGradientBrush x:Key="TextBoxBorder" EndPoint="0,20" StartPoint="0,0" MappingMode="Absolute">
    <GradientStop Color="#ABADB3" Offset="0.05"/>
    <GradientStop Color="#E2E3EA" Offset="0.07"/>
    <GradientStop Color="#E3E9EF" Offset="1"/>
</LinearGradientBrush>
<Style x:Key="LabelValidationTextBox" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
    <Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Padding" Value="1"/>
    <Setter Property="AllowDrop" Value="true"/>
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBox}">
                <StackPanel Orientation="Vertical">
                    <Microsoft_Windows_Themes:ListBoxChrome x:Name="Bd" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" RenderMouseOver="{TemplateBinding IsMouseOver}">
                        <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </Microsoft_Windows_Themes:ListBoxChrome>
                    <Label StackPanel.ZIndex="-1" Name="errorLabel" Height="22" Margin="0,-22,0,0" Background="Red" Foreground="White" FontSize="9" Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Validation.Errors)[0].ErrorContent}" />
                </StackPanel>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                    </Trigger>
                    <Trigger Property="Validation.HasError" Value="True">
                        <Trigger.EnterActions>
                            <BeginStoryboard>
                                <Storyboard TargetName="errorLabel" TargetProperty="Margin">
                                    <ThicknessAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="Margin">
                                        <SplineThicknessKeyFrame KeyTime="0:0:0.0" Value="0,-22,0,0"/>
                                        <SplineThicknessKeyFrame KeyTime="0:0:0.5" Value="0,0,0,0"/>
                                    </ThicknessAnimationUsingKeyFrames>
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.EnterActions>
                        <Trigger.ExitActions>
                            <BeginStoryboard>
                                <Storyboard TargetName="errorLabel" TargetProperty="Margin">
                                    <ThicknessAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="Margin">
                                        <SplineThicknessKeyFrame KeyTime="0:0:0.0" Value="0,0,0,0"/>
                                        <SplineThicknessKeyFrame KeyTime="0:0:0.5" Value="0,-22,0,0"/>
                                    </ThicknessAnimationUsingKeyFrames>
                                </Storyboard>
                            </BeginStoryboard>
                        </Trigger.ExitActions>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<强>更新

添加了标签的边距动画。当Validation.HasError为True时,它将“滑出”TextBox,当Validation.HasError为False时,它将“滑回”到TextBox。

答案 1 :(得分:1)

您可以使用Visual State Manager并自定义无效状态,而不是使用ErrorTemplate。通过这样做,除了能够将您的更改集成到实际控件(影响布局)之外,您还可以非常轻松地为状态更改设置动画。

如果您需要有关视觉状态的更多指导,请不要犹豫。